WPF错误:找不到目标元素的管理FrameworkElement

KDP*_*KDP 76 wpf binding datagrid image multidatatrigger

我有一个带有图像的Row的数据网格.此图像与某个状态的触发器绑定.当状态改变时我想改变图像.

模板本身在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,
    });
}
Run Code Online (Sandbox Code Playgroud)

数据网格:

<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>
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

现在,当我启动项目时,图像没有显示,我收到此错误:

System.Windows.Data错误:2:找不到目标元素的管理FrameworkElement或FrameworkContentElement.BindingExpression:路径= HeaderItems [0]; 的DataItem = NULL; target元素是'DataGridTemplateColumn'(HashCode = 26950454); target属性是'Header'(类型'Object')

为什么会出现此错误?

WPF*_*-it 148

遗憾的是,任何DataGridColumn托管DataGrid.Columns的都不是Visual树的一部分,因此没有连接到datagrid的数据上下文.所以绑定不会与他们的特性,如工作VisibilityHeader等(尽管这些特性都是有效的依赖属性!).

现在你可能想知道这怎么可能?是不是他们的Binding属性应该绑定到数据上下文?嗯它只是一个黑客.绑定并不真正起作用.它实际上是复制/克隆此绑定对象并使用它来显示自己的内容的datagrid单元格!

现在回到解决您的问题,我假设这HeaderItems是对象的属性,设置为DataContext您的父View.我们可以DataContext视图连接到任何DataGridColumn我们称之为的东西ProxyElement.

下面的例子说明了如何将逻辑子连接在一起,例如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>
Run Code Online (Sandbox Code Playgroud)

如果我没有实现ProxyElement hack,上面的视图遇到了你发现的相同的绑定错误.ProxyElement是任何从主视图中窃取的FrameworkElement,DataContext并将其提供给逻辑子,如ContextMenuDataGridColumn.为此,它必须作为一个Content隐藏ContentControl在同一个视图下的托管.

我希望这能指导你正确的方向.

  • 我发现必须使用这个hacky代理的东西真的令人失望,但我找不到另一种方法来实现相同的功能,否则......谢谢. (22认同)
  • 这对我不起作用,但在阅读Josh Smith关于虚拟分支的文章后,我尝试在我的根控件上添加OneWayToSource绑定来设置"ProxyElement"DataContext并且这很有效. (2认同)
  • FYI上下文菜单不相同,并且具有非代理方法.上下文菜单有一个公开的属性`Parent`,而`DataGridTextColumn`没有公开它的`DataGridOwner`属性.在我的回答[Context Menu Binding to Parent Window的Datacontext]中查看如何通过RelativeSource绑定完成上下文项绑定(http://stackoverflow.com/questions/26359091/context-menu-binding-to-parent-windows-datacontext/ 26383463#26383463) (2认同)

Fer*_*ndr 12

StaticResource在接受的答案中使用 a 的略短的替代方法是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>
Run Code Online (Sandbox Code Playgroud)

这样做的主要好处是:如果你已经有这一个元素不是一个DataGrid的祖先(即StackPanel上面的例子),你可以给它一个名字,并把它作为x:Reference代替,因此不需要定义任何虚FrameworkElement根本。

如果您尝试引用祖先,XamlParseException由于循环依赖,您将在运行时得到一个。