2011-10-05 241 views
57

我有一个具有图像的行的datagrid。该图像与触发器绑定到某个状态。当状态改变时,我想改变图像。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:

<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 Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=HeaderItems[0]; DataItem=null; target element is 'DataGridTemplateColumn' (HashCode=26950454); target property is 'Header' (type 'Object')

为什么会显示此错误?

+1

我检查了上述答案的解决方案,但它不适用于我的情况。当我切换到另一个解决方案,如链接http://www.thomaslevesque。COM/2011/03/21/WPF的如何做绑定到数据时,最DataContext的 - 是 - 不继承/。这个想法与解决方案相同,而不是使用FrameworkElement,他们创建了另一个类。然后它适用于我。 – leo5th

+0

对于通过搜索错误消息在这里结束的其他人:这个类似问题的答案帮助我很容易地解决问题http://stackoverflow.com/a/18657986/4961688 –

回答

118

很遗憾,DataGrid.Columns下的DataGridColumn不是Visual树的一部分,因此没有连接到数据网格的数据上下文。因此,绑定不能与其属性(如VisibilityHeader等)一起使用(尽管这些属性是有效的依赖项属性!)。

现在你可能知道怎么可能?他们的Binding属性是否应该绑定到数据上下文?那简直就是黑客。绑定不是真的有效。它实际上是拷贝/克隆这个绑定对象,并用它来显示自己的内容的数据网格单元!

现在回到解决您的问题,我假设HeaderItems是设置为您的父视图的DataContext对象的属性。我们罐头通过我们所说的ProxyElement连接视图的DataContext到任何DataGridColumn。下面

的例子说明了如何将逻辑子等连接为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是从主视图中盗取DataContext并将其提供给逻辑孩子(如ContextMenuDataGridColumn)的任何FrameworkElement。为此,它必须作为Content托管到不可见的ContentControl之下,这是在相同的视图下。

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

+17

我发现必须使用这个hacky代理的东西真的disapointing,但我找不到另一种方式来实现相同的功能,否则...谢谢。 –

+2

这并不适用于我,但在阅读Josh Smith关于虚拟分支的文章后,我尝试在我的根控件上添加OneWayToSource绑定来设置“ProxyElement”DataContext,并且工作正常。 – jpierson

+0

@jpierson,你在使用Silverlight吗?因为它在'WPF'中适合我。对于silverlight,实现是不同的。 –