C# 从ControlTemplate绑定到ViewModel
我已经把我的问题简化为一个简单的例子:我的DataGrid是由一个ControlTemplate定义的,在这个ControlTemplate中,我不能绑定到ViewModel中的任何东西 这是简化的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!"; }
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部分中