web-dev-qa-db-ja.com

WPFエラー:ターゲット要素の管理FrameworkElementが見つかりません

画像のある行を持つデータグリッドを持っています。このイメージは、特定の状態へのトリガーにバインドされています。状態が変わったら、画像を変更したいです。

テンプレート自体は、DataGridTemplateColumnのHeaderStyleで設定されます。このテンプレートにはいくつかのバインディングがあります。最初のバインド日は、その日を示し、州はトリガーで画像を変更します。

これらのプロパティは、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>

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エラー:2:ターゲット要素の管理FrameworkFrameworkまたはFrameworkContentElementが見つかりません。 BindingExpression:Path = HeaderItems [0]; DataItem = null;ターゲット要素は 'DataGridTemplateColumn'(HashCode = 26950454)です。ターゲットプロパティは 'Header'(タイプ 'Object')です

このエラーが表示されるのはなぜですか?

74
KDP

悲しいことに、DataGrid.ColumnsでホストされているDataGridColumnVisualツリーの一部ではないため、データグリッドのデータコンテキストに接続されていません。したがって、バインディングはVisibilityHeaderなどのプロパティでは機能しません(これらのプロパティは有効な依存関係プロパティです!)。

今、あなたはそれがどのように可能か疑問に思うかもしれません?それらのBindingプロパティはデータコンテキストにバインドされるはずではありませんか?まあそれは単にハックです。バインディングは実際には機能しません。 copy/cloneこのバインディングオブジェクトは、データグリッドセルであり、独自のコンテンツの表示に使用します!

問題の解決に戻って、HeaderItemsは親ビューのDataContextとして設定されるオブジェクトのプロパティであると仮定します。私たちはcanビューのDataContextを任意のDataGridColumnProxyElement

以下の例は、ContextMenuDataGridColumnなどの論理子を親ビューの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は、メインビューのstealsDataContextであり、ContextMenuDataGridColumnなどの論理子に提供するFrameworkElementです。そのため、同じビューの下にある不可視のContentContentControlとしてホストする必要があります。

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

142
WPF-it