1. ホーム
  2. wpf

[解決済み] WPFエラー。エラー: ターゲット要素に対応する FrameworkElement が見つかりません。

2023-01-11 15:37:11

質問

私は DataGrid があり、その行には画像があります。この画像はトリガーで特定の状態にバインドされています。状態が変化したら、画像を変更したい。

テンプレート自体は HeaderStyleDataGridTemplateColumn . このテンプレートにはいくつかのバインディングがあります。最初のバインディングDayは、今日が何日目かを示し、Stateはトリガーで画像を変更します。

これらのプロパティはViewModelに設定されています。

プロパティです。

public class HeaderItem
{
    public string Day { get; set; }
    public ValidationStatus State { get; set; }
}

this.HeaderItems = new ObservableCollection<HeaderItem>();
for (int i = 1; i < 15; i++)
{
    this.HeaderItems.Add(new HeaderItem()
    {
        Day = i.ToString(),
        State = ValidationStatus.Nieuw,
    });
}

データグリッドです。

<DataGrid x:Name="PersoneelsPrestatiesDataGrid" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
              AutoGenerateColumns="False" SelectionMode="Single" ItemsSource="{Binding CaregiverPerformances}" FrozenColumnCount="1" >

    <DataGridTemplateColumn HeaderStyle="{StaticResource headerCenterAlignment}" Header="{Binding HeaderItems[1]}" Width="50">
        <DataGridTemplateColumn.CellEditingTemplate>
            <DataTemplate>
                <TextBox Text="{ Binding Performances[1].Duration,Converter={StaticResource timeSpanConverter},Mode=TwoWay}"/>
            </DataTemplate>
        </DataGridTemplateColumn.CellEditingTemplate>

        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <TextBlock TextAlignment="Center" Text="{ Binding Performances[1].Duration,Converter={StaticResource timeSpanConverter}}"/>
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn> 
</DataGrid>

データグリッドのHeaderStyleTemplateです。

<Style x:Key="headerCenterAlignment" TargetType="{x:Type DataGridColumnHeader}">
    <Setter Property="HorizontalContentAlignment" Value="Center"/>

    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition />
                        <RowDefinition />
                    </Grid.RowDefinitions>

                    <TextBlock Grid.Row="0" Text="{Binding Day}" />
                    <Image x:Name="imageValidation" Grid.Row="1" Width="16" Height="16" Source="{StaticResource imgBevestigd}" />
                </Grid>

                <ControlTemplate.Triggers>
                    <MultiDataTrigger >
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{Binding State}" Value="Nieuw"/>                                 
                        </MultiDataTrigger.Conditions>
                        <Setter TargetName="imageValidation" Property="Source" Value="{StaticResource imgGeenStatus}"/>
                    </MultiDataTrigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

現在、プロジェクトを起動すると、画像は表示されず、このエラーが発生します。

System.Windows.Data Error: 2 : ターゲット要素のための統治された FrameworkElement または FrameworkContentElement を見つけることができません。BindingExpression:Path=HeaderItems[0]; DataItem=null; target element is 'DataGridTemplateColumn' (HashCode=26950454); target property is 'Header' (type 'Object').

なぜこのようなエラーが表示されるのでしょうか?

どのように解決するのですか?

悲しいかな、どんな DataGridColumn の下にホストされている DataGrid.Columns の一部ではありません。 Visual ツリーの一部ではないので、データグリッドのデータコンテキストに接続されていません。したがって、バインディングはそのプロパティ、たとえば Visibility または Header など(これらのプロパティは有効な依存性プロパティですが!)。

さて、どうしてそんなことが可能なのか不思議に思うかもしれません。彼らの Binding プロパティはデータコンテキストにバインドされているはずではありませんか?これは単にハッキングなのです。バインディングは実際には機能しません。実際にはデータグリッドセルに をコピーします。 / クローン このバインディングオブジェクトを複製して、自分自身のコンテンツを表示するために使用します。

さて、問題の解決に戻りますが、私が想定しているのは HeaderItems として設定されているオブジェクトのプロパティは DataContext として設定されているオブジェクトのプロパティです。我々は ができます。 を接続します。 DataContext を任意の DataGridColumn と呼ぶものを経由して ProxyElement .

以下の例では、論理子である ContextMenu または DataGridColumn を親ビューの DataContext

 <Window x:Class="WpfApplicationMultiThreading.Window5"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"        
         xmlns:vb="http://schemas.microsoft.com/wpf/2008/toolkit"
         Title="Window5" Height="300" Width="300" >
  <Grid x:Name="MyGrid">
    <Grid.Resources>
        <FrameworkElement x:Key="ProxyElement" DataContext="{Binding}"/>
    </Grid.Resources>
    <Grid.DataContext>
         <TextBlock Text="Text Column Header" Tag="Tag Columne Header"/>
    </Grid.DataContext>
    <ContentControl Visibility="Collapsed"
             Content="{StaticResource ProxyElement}"/>
    <vb:DataGrid AutoGenerateColumns="False" x:Name="MyDataGrid">
        <vb:DataGrid.ItemsSource>
            <x:Array Type="{x:Type TextBlock}">
                <TextBlock Text="1" Tag="1.1"/>
                <TextBlock Text="2" Tag="1.2"/>
                <TextBlock Text="3" Tag="2.1"/>
                <TextBlock Text="4" Tag="2.2"/>
            </x:Array>
        </vb:DataGrid.ItemsSource>
        <vb:DataGrid.Columns>
            <vb:DataGridTextColumn
                       Header="{Binding DataContext.Text,
                                     Source={StaticResource ProxyElement}}"
                       Binding="{Binding Text}"/>
            <vb:DataGridTextColumn
                       Header="{Binding DataContext.Tag,
                                     Source={StaticResource ProxyElement}}"
                       Binding="{Binding Tag}"/>
        </vb:DataGrid.Columns>
    </vb:DataGrid>
  </Grid>
</Window>

上のビューは、もし私がProxyElementハックを実装していなければ、あなたが発見したのと同じバインディングエラーに遭遇しました。ProxyElement とは、以下のような FrameworkElement のことです。 を盗みます。 という DataContext のような論理的な子ビューに提供します。 ContextMenu または DataGridColumn . そのためには Content を目に見えない ContentControl に変換されます。

これが正しい方向へ導いてくれることを願っています。