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


87

私が持っているDataGridイメージを持っている行で。この画像は、トリガーで特定の状態にバインドされています。状態が変わったら画像を変えたいです。

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

これらのプロパティは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エラー:2:ターゲット要素の管理FrameworkElementまたはFrameworkContentElementが見つかりません。BindingExpression:Path = HeaderItems [0]; DataItem = null; ターゲット要素は 'DataGridTemplateColumn'(HashCode = 26950454); ターゲットプロパティは「ヘッダー」(タイプ「オブジェクト」)です。

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


4
上記の回答済みの解決策を確認しましたが、私の場合は機能しません。リンクthomaslevesque.com/2011/03/21/のように別のソリューションに切り替えると。考え方はソリューションと同じですが、FrameworkElementを使用する代わりに、別のクラスを作成しました。それからそれは私のために働きます。
leo5th 2015年

エラーメッセージを検索してここにたどり着く他の人のために:この同様の質問の答えは、問題をかなり簡単に解決するのに役立ちましたstackoverflow.com/a/18657986/4961688
Tim Pohlmann 2017

回答:


165

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

今、あなたはそれがどのように可能であるか疑問に思うかもしれませんか?それらの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は、メインビューからを盗み、またはDataContextなどの論理的な子に提供する任意のFrameworkElementです。そのためには、同じビューの下にあるインビジブルにとしてホストする必要があります。ContextMenuDataGridColumnContentContentControl

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


25
このハッキーなプロキシを使用しなければならないのは本当に残念ですが、それ以外の方法で同じ機能を実現する別の方法を見つけることはできません...ありがとうございます。
アレックスホープオコナー

2
これは私には機能しませんでしたが、仮想ブランチに関するJosh Smithの記事を読んだ後、ルートコントロールにOneWayToSourceバインディングを追加して、「ProxyElement」DataContextを設定しようとしました。
jpierson 2012年

1
いいえ。上記のソリューションは、.NET3.5に非常によく適合します。
WPF-それは

1
この答えは古いものですが、.NET4.0に対してはまだ役立ちます。DataContextを列にコピーすることに関する多くの答えは機能していないようです。ビューモデルのプロパティに応じて列を表示/非表示にする必要があり、このソリューションはうまく機能しました。また、コードが背後にない場合でも、コードレビューで外交上の問題が発生することはありません。
James_UK_DEV 2014

3
FYIコンテキストメニューは同じではなく、非プロキシの回避策があります。コンテキストメニューには公開されたプロパティParentがありますが、DataGridTextColumnはそのDataGridOwnerプロパティを公開していません。バインディングコンテキスト項目が私の答えの中にバインディングRelativeSourceを介して達成される方法を参照してください親ウィンドウのDataContextのへのバインディングコンテキストメニュー
ΩmegaMan

8

StaticResource受け入れられた答えのようにを使用するためのわずかに短い代替案はx:Reference次のとおりです。

<StackPanel>

    <!--Set the DataContext here if you do not want to inherit the parent one-->
    <FrameworkElement x:Name="ProxyElement" Visibility="Collapsed"/>

    <DataGrid>
        <DataGrid.Columns>
            <DataGridTextColumn
                Header="{Binding DataContext.Whatever, Source={x:Reference ProxyElement}}"
                Binding="{Binding ...}" />
        </DataGrid.Columns>
    </DataGrid>

</StackPanel>

すでにある要素がある場合:これの主な利点はありません(つまり、DataGridの祖先ではないStackPanel上記の例では)、あなたはそれに名前を付け、としてそれを使用することができx:Reference、代わりに、したがって任意のダミーを定義する必要がありませんFrameworkElementまったく。

祖先を参照しようとXamlParseExceptionすると、周期的な依存関係があるため、実行時に取得します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.