从ControlTemplate绑定到ViewModel

时间:2015-11-13 13:41:22

标签: c# wpf mvvm data-binding

我已经将我的问题简化为一个最小的例子:我的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中的任何内容?我无法想象这是不可能的。

为了完整性,这些是记录到输出的错误。他们的订单符合XAML的顺序。

  

System.Windows.Data错误:40:BindingExpression路径错误:   在'object'''DataGridTextColumn'上找不到'DataContext'属性   (的HashCode = 28365320)”。 BindingExpression:路径= DataContext.Text1;   DataItem ='DataGridTextColumn'(HashCode = 28365320);目标元素是   'DataGridTextColumn'(HashCode = 28365320);目标属性是'标题'   (输入'对象')

     

System.Windows.Data错误:40:BindingExpression路径错误:'Text1'   'object'''DataGridTextColumn'上找不到属性   (的HashCode = 54811268)”。 BindingExpression:路径=文本1;   DataItem ='DataGridTextColumn'(HashCode = 54811268);目标元素是   'DataGridTextColumn'(HashCode = 54811268);目标属性是'标题'   (输入'对象')

     

System.Windows.Data错误:2:找不到管理FrameworkElement   或目标元素的FrameworkContentElement。   BindingExpression:路径= DataContext.Text1;的DataItem = NULL;目标   element是'DataGridTextColumn'(HashCode = 55195297);目标财产   是'标题'(类型'对象')

     

System.Windows.Data错误:2:找不到管理FrameworkElement   或目标元素的FrameworkContentElement。   BindingExpression:路径=文本1;的DataItem = NULL;目标元素是   'DataGridTextColumn'(HashCode = 38845522);目标属性是'标题'   (输入'对象')

     

System.Windows.Data错误:4:找不到绑定源   参考'RelativeSource FindAncestor,   AncestorType ='System.Windows.Window',AncestorLevel ='1''。   BindingExpression:路径= DataContext.Text1;的DataItem = NULL;目标   element是'DataGridTextColumn'(HashCode = 2399386);目标属性是   '标题'(输入'对象')

     

System.Windows.Data错误:4:找不到绑定源   参考'RelativeSource FindAncestor,   AncestorType ='System.Windows.Window',AncestorLevel ='1''。   BindingExpression:路径=文本1;的DataItem = NULL;目标元素是   'DataGridTextColumn'(HashCode = 31265986);目标属性是'标题'   (输入'对象')

     

System.Windows.Data错误:2:找不到管理FrameworkElement   或目标元素的FrameworkContentElement。   BindingExpression:路径= DataContext.Text1;的DataItem = NULL;目标   element是'DataGridTextColumn'(HashCode = 6837024);目标属性是   '标题'(输入'对象')

     

System.Windows.Data错误:2:找不到管理FrameworkElement   或目标元素的FrameworkContentElement。   BindingExpression:路径=文本1;的DataItem = NULL;目标元素是   'DataGridTextColumn'(HashCode = 17422861);目标属性是'标题'   (输入'对象')

     

System.Windows.Data错误:2:找不到管理FrameworkElement   或目标元素的FrameworkContentElement。   BindingExpression:路径= Content.DataContext.Text1;的DataItem = NULL;   target元素是'DataGridTextColumn'(HashCode = 32669489);目标   属性是'标题'(类型'对象')

     

System.Windows.Data错误:2:找不到管理FrameworkElement   或目标元素的FrameworkContentElement。   BindingExpression:路径= Content.Text1;的DataItem = NULL;目标元素是   'DataGridTextColumn'(HashCode = 22361045);目标属性是'标题'   (输入'对象')

     

System.Windows.Data错误:2:找不到管理FrameworkElement   或目标元素的FrameworkContentElement。   BindingExpression:路径= DataContext.Text1;的DataItem = NULL;目标   element是'DataGridTextColumn'(HashCode = 7953856);目标属性是   '标题'(输入'对象')

     

System.Windows.Data错误:2:找不到管理FrameworkElement   或目标元素的FrameworkContentElement。   BindingExpression:路径=文本1;的DataItem = NULL;目标元素是   'DataGridTextColumn'(HashCode = 65911433);目标属性是'标题'   (输入'对象')

2 个答案:

答案 0 :(得分:2)

11 设置HeaderTemplate,如下所示

DataGridTextColumn

答案 1 :(得分:0)

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

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

x:Reference使用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部分内,并且不能位于外部{ {1}}。在后一种情况下,引用将无法工作,因为它无法解析。 (如果有人知道解决方案,那将是受欢迎的)