C# 从ControlTemplate绑定到ViewModel

C# 从ControlTemplate绑定到ViewModel,c#,wpf,mvvm,data-binding,C#,Wpf,Mvvm,Data Binding,我已经把我的问题简化为一个简单的例子:我的DataGrid是由一个ControlTemplate定义的,在这个ControlTemplate中,我不能绑定到ViewModel中的任何东西 这是简化的ViewModel: public class ViewModel : PropertyChangedBase { private string text1; public ViewModel() { this.text1 = "tx1!"; }

我已经把我的问题简化为一个简单的例子:我的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
。我通过谷歌找到的大多数东西都是建议
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路径错误: 在“对象”“DataGridTextColumn”上找不到“DataContext”属性 (HashCode=28365320)”。BindingExpression:Path=DataContext.Text1; DataItem='DataGridTextColumn'(HashCode=28365320);目标元素是 “DataGridTextColumn”(HashCode=28365320);目标属性为“Header” (键入“对象”)

System.Windows.Data错误:40:BindingExpression路径错误:“Text1” 在“对象”“DataGridTextColumn”上找不到属性 (HashCode=54811268)”。BindingExpression:Path=Text1; DataItem='DataGridTextColumn'(HashCode=54811268);目标元素是 “DataGridTextColumn”(HashCode=54811268);目标属性为“Header” (键入“对象”)

System.Windows.Data错误:2:找不到治理框架元素 或目标元素的FrameworkContentElement。 BindingExpression:Path=DataContext.Text1;DataItem=null;目标 元素是“DataGridTextColumn”(HashCode=55195297);目标属性 是“头”(类型为“对象”)

System.Windows.Data错误:2:找不到治理框架元素 或目标元素的FrameworkContentElement。 BindingExpression:Path=Text1;DataItem=null;目标元素是 “DataGridTextColumn”(HashCode=38845522);目标属性为“Header” (键入“对象”)

System.Windows.Data错误:4:找不到与绑定的源 参考“相对资源查找器”, AncestorType='System.Windows.Window',AncestorLevel='1'。 BindingExpression:Path=DataContext.Text1;DataItem=null;目标 元素是“DataGridTextColumn”(HashCode=2399386);目标属性为 “标题”(类型“对象”)

System.Windows.Data错误:4:找不到与绑定的源 参考“相对资源查找器”, AncestorType='System.Windows.Window',AncestorLevel='1'。 BindingExpression:Path=Text1;DataItem=null;目标元素是 “DataGridTextColumn”(HashCode=31265986);目标属性为“Header” (键入“对象”)

System.Windows.Data错误:2:找不到治理框架元素 或目标元素的FrameworkContentElement。 BindingExpression:Path=DataContext.Text1;DataItem=null;目标 元素为“DataGridTextColumn”(HashCode=6837024);目标属性为 “标题”(类型“对象”)

System.Windows.Data错误:2:找不到治理框架元素 或目标元素的FrameworkContentElement。 BindingExpression:Path=Text1;DataItem=null;目标元素是 “DataGridTextColumn”(HashCode=17422861);目标属性为“Header” (键入“对象”)

System.Windows.Data错误:2:找不到治理框架元素 或目标元素的FrameworkContentElement。 BindingExpression:Path=Content.DataContext.Text1;DataItem=null; 目标元素是“DataGridTextColumn”(HashCode=32669489);目标 属性为“头”(类型为“对象”)

System.Windows.Data错误:2:找不到治理框架元素 或目标元素的FrameworkContentElement。 BindingExpression:Path=Content.Text1;DataItem=null;目标元素是 “DataGridTextColumn”(HashCode=22361045);目标属性为“Header” (键入“对象”)

System.Windows.Data错误:2:找不到治理框架元素 或目标元素的FrameworkContentElement。 BindingExpression:Path=DataContext.Text1;DataItem=null;目标 元素是“DataGridTextColumn”(HashCode=7953856);目标属性为 “标题”(类型“对象”)

System.Windows.Data错误:2:找不到治理框架元素 或目标元素的FrameworkContentElement。 BindingExpression:Path=Text1;DataItem=null;目标元素是 “DataGridTextColumn”(HashCode=65911433);目标属性为“Header” (键入“对象”)


DataGridTextColumn
设置
HeaderTemplate
,如下所示

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

通过所有提示,我发现
DataGridTextColumn
既不是可视树的一部分,也不是逻辑树的一部分。这就是
ElementName
RelativeSource
不起作用的原因。这个关于
DataGridTextColumn
的答案解释了这一点,并给出了一个可能的解决方案,包括
Source
x:Reference

@Anand Murali的答案很有效,但不能应用于
可见性
——这不是问题的一部分,因为我将其最小化了。因此,我接受这一条,并将在这一条中提供更多信息

使用
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
,该模板必须位于同一文件中的
XAML部分中