首页 文章

从ControlTemplate绑定到ViewModel

提问于
浏览
2

我已经将我的问题简化为一个最小的例子:我的DataGrid是由ControlTemplate定义的,在ControlTemplate中我无法绑定到我的ViewModel中的任何内容 .

这是简化的ViewModel:

public class ViewModel : PropertyChangedBase
{
    private string text1;

    public ViewModel()
    {
        this.text1 = "tx1!";
    }

    public string Text1
    {
        get { return text1; }
        set
        {
            if (value == text1) return;
            text1 = value;
            NotifyOfPropertyChange(() => Text1);
        }
    }
}

我尝试用几种方法绑定到 Text1 . 我通过Google找到的大多数内容都建议 FindAncestor ,但它也不起作用:

<Window x:Class="DataGridTemplateBinding.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:DataGridTemplateBinding"
        Title="MainWindow" Height="350" Width="525"
        x:Name="LayoutRoot"
        >
    <Window.Resources>
        <ControlTemplate x:Key="TableTemplate">
            <DataGrid>
                <DataGrid.Columns>
                    <DataGridTextColumn Header="Column 1" />
                    <!-- by ElementName -->
                    <DataGridTextColumn Header="{Binding DataContext.Text1, ElementName=LayoutRoot}" />
                    <DataGridTextColumn Header="{Binding Text1, ElementName=LayoutRoot}" />

                    <!-- by Ancestor type (Window) -->
                    <DataGridTextColumn Header="{Binding DataContext.Text1, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" />
                    <DataGridTextColumn Header="{Binding Text1, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" />

                    <!-- by templated parent -->
                    <DataGridTextColumn Header="{Binding DataContext.Text1, RelativeSource={RelativeSource TemplatedParent}}" />
                    <DataGridTextColumn Header="{Binding Text1, RelativeSource={RelativeSource TemplatedParent}}" />

                    <!-- by self?? -->
                    <DataGridTextColumn Header="{Binding DataContext.Text1, RelativeSource={RelativeSource Self}}" />
                    <DataGridTextColumn Header="{Binding Text1, RelativeSource={RelativeSource Self}}" />

                    <DataGridTextColumn Header="{Binding Content.DataContext.Text1, RelativeSource={RelativeSource TemplatedParent}}" />
                    <DataGridTextColumn Header="{Binding Content.Text1, RelativeSource={RelativeSource TemplatedParent}}" />

                    <DataGridTextColumn Header="{Binding DataContext.Text1}" />
                    <DataGridTextColumn Header="{Binding Text1}" />

                    <DataGridTextColumn Header="Column End" />
                </DataGrid.Columns>
            </DataGrid>
        </ControlTemplate>
    </Window.Resources>
    <Window.DataContext>
        <local:ViewModel />
    </Window.DataContext>
    <Grid>
        <DataGrid Template="{StaticResource TableTemplate}" />
    </Grid>
</Window>

模板中的列如何绑定到ViewModel中的任何内容?我不能想象这是不可能的 .


为完整起见,这些是记录到输出的错误 . 他们的订单确实 not 对应于XAML的顺序 .

System.Windows.Data错误:40:BindingExpression路径错误:在'object'''DataGridTextColumn'(HashCode = 28365320)'上找不到'DataContext'属性 . BindingExpression:路径= DataContext.Text1; DataItem ='DataGridTextColumn'(HashCode = 28365320); target元素是'DataGridTextColumn'(HashCode = 28365320);目标属性是' Headers '(类型'对象')System.Windows.Data错误:40:BindingExpression路径错误:在'对象'''DataGridTextColumn'(HashCode = 54811268)'上找不到'Text1'属性 . BindingExpression:路径=文本1; DataItem ='DataGridTextColumn'(HashCode = 54811268); target元素是'DataGridTextColumn'(HashCode = 54811268); target属性是'Header'(类型'Object')System.Windows.Data错误:2:无法为目标元素找到管理FrameworkElement或FrameworkContentElement . BindingExpression:路径= DataContext.Text1;的DataItem = NULL; target元素是'DataGridTextColumn'(HashCode = 55195297); target属性是'Header'(类型'Object')System.Windows.Data错误:2:无法为目标元素找到管理FrameworkElement或FrameworkContentElement . BindingExpression:路径=文本1;的DataItem = NULL; target元素是'DataGridTextColumn'(HashCode = 38845522);目标属性是' Headers '(类型'对象')System.Windows.Data错误:4:找不到与引用'RelativeSource FindAncestor绑定的源,AncestorType ='System.Windows.Window',AncestorLevel ='1'' . BindingExpression:路径= DataContext.Text1;的DataItem = NULL; target元素是'DataGridTextColumn'(HashCode = 2399386);目标属性是' Headers '(类型'对象')System.Windows.Data错误:4:找不到与引用'RelativeSource FindAncestor绑定的源,AncestorType ='System.Windows.Window',AncestorLevel ='1'' . BindingExpression:路径=文本1;的DataItem = NULL; target元素是'DataGridTextColumn'(HashCode = 31265986); target属性是'Header'(类型'Object')System.Windows.Data错误:2:无法为目标元素找到管理FrameworkElement或FrameworkContentElement . BindingExpression:路径= DataContext.Text1;的DataItem = NULL; target元素是'DataGridTextColumn'(HashCode = 6837024); target属性是'Header'(类型'Object')System.Windows.Data错误:2:无法为目标元素找到管理FrameworkElement或FrameworkContentElement . BindingExpression:路径=文本1;的DataItem = NULL; target元素是'DataGridTextColumn'(HashCode = 17422861); target属性是'Header'(类型'Object')System.Windows.Data错误:2:无法为目标元素找到管理FrameworkElement或FrameworkContentElement . BindingExpression:路径= Content.DataContext.Text1;的DataItem = NULL; target元素是'DataGridTextColumn'(HashCode = 32669489); target属性是'Header'(类型'Object')System.Windows.Data错误:2:无法为目标元素找到管理FrameworkElement或FrameworkContentElement . BindingExpression:路径= Content.Text1;的DataItem = NULL; target元素是'DataGridTextColumn'(HashCode = 22361045); target属性是'Header'(类型'Object')System.Windows.Data错误:2:无法为目标元素找到管理FrameworkElement或FrameworkContentElement . BindingExpression:路径= DataContext.Text1;的DataItem = NULL; target元素是'DataGridTextColumn'(HashCode = 7953856); target属性是'Header'(类型'Object')System.Windows.Data错误:2:无法为目标元素找到管理FrameworkElement或FrameworkContentElement . BindingExpression:路径=文本1;的DataItem = NULL; target元素是'DataGridTextColumn'(HashCode = 65911433); target属性是'Header'(类型'Object')

2 回答

  • 0

    DataGridTextColumn 设置 HeaderTemplate ,如下所示

    <DataGridTextColumn  >
        <DataGridTextColumn.HeaderTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.Text1}"></TextBlock>
            </DataTemplate>
        </DataGridTextColumn.HeaderTemplate>
    </DataGridTextColumn>
    
  • 2

    在我发现的所有提示中, DataGridTextColumn 既不是可视树的一部分,也不是逻辑树的一部分 . 这应该是 ElementNameRelativeSource 不起作用的原因 . 关于 DataGridTextColumn 的这个答案解释了这一点,并给出了一个可能的答案解决方案 Sourcex:ReferenceDataGridTextColumn Visibility Binding

    @Anand Murali的答案有效但不能应用于 Visibility - 这不是问题的一部分,因为我把它简化了 . 所以我接受了这一个,并将提供更多信息 .

    使用 x:Reference for Visibility 它可以像:

    <DataGridTextColumn Binding="{Binding Data.OrderNumber}" Header="Order Number" Visibility="{Binding DataContext.ShowColumnOrderNumber, Source={x:Reference LayoutRoot}, Converter={StaticResource BooleanToVisibilityConverter}}" />
    

    但是:我的例子我使用了 ControlTemplate 并且要使 x:Reference 工作,此模板必须位于同一文件的 .Resources XAML部分内,并且不能位于外部 ResourceDictionary . 在后一种情况下,引用将无法工作,因为它无法解析 . (如果有人知道解决方案,那将是受欢迎的)

相关问题