首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >WPF错误:找不到目标元素的管理FrameworkElement

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

Stack Overflow用户
提问于 2011-10-05 20:00:57
回答 3查看 58K关注 0票数 98

我有一个DataGrid,它的一行有一个图像。此图像通过触发器绑定到特定状态。当状态改变时,我想要改变图像。

模板本身在DataGridTemplateColumnHeaderStyle上设置。此模板有一些绑定。第一个binding Day显示是哪一天,State使用触发器更改图像。

这些属性是在ViewModel中设置的。

属性:

代码语言:javascript
复制
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,
    });
}

数据网格:

代码语言:javascript
复制
<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:

代码语言:javascript
复制
<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;DataItem=null;目标元素是“DataGridTemplateColumn”(HashCode=26950454);目标属性是“Header”(类型为“Object”)

为什么会显示此错误?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-10-05 21:00:57

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

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

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

下面的示例说明了如何将逻辑子视图(如ContextMenuDataGridColumn )连接到父视图的DataContext

代码语言:javascript
复制
 <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并将其提供给逻辑子视图的任何DataContext,比如ContextMenuDataGridColumn。为此,必须将其作为Content托管到同一视图下的不可见ContentControl中。

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

票数 173
EN

Stack Overflow用户

发布于 2020-04-10 17:44:10

在公认的答案中,使用StaticResource的另一种更短的替代方法是x:Reference

代码语言:javascript
复制
<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>

这样做的主要优点是:如果你已经有一个元素不是数据网格的祖先(例如,上面例子中的 StackPanel ),你只需给它一个名字,并将其用作x:Reference,因此根本不需要定义任何虚拟的FrameworkElement

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

票数 14
EN

Stack Overflow用户

发布于 2021-04-07 05:36:24

没有代理的方法是在构造函数中设置绑定:

代码语言:javascript
复制
var i = 0;
var converter = new BooleanToVisibilityConverter();
foreach(var column in DataGrid.Columns)
{
    BindingOperations.SetBinding(column, DataGridColumn.VisibilityProperty, new Binding($"Columns[{i++}].IsSelected")
    { 
        Source = ViewModel,
        Converter = converter,
    });
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7660967

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档