绑定到 DataTemplate 中的视图模型属性
Posted
技术标签:
【中文标题】绑定到 DataTemplate 中的视图模型属性【英文标题】:Binding to a viewmodel property in a DataTemplate 【发布时间】:2013-03-22 19:55:56 【问题描述】:我对 XAML 还很陌生,但很喜欢学习它。我真正苦苦挣扎的事情是将属性绑定到 DataTemplate
中的元素。
我创建了一个简单的 WPF 示例来(希望)解释我的问题。
在这个例子中,我试图将CheckBox
中的DataTemplate
的Visibility
属性绑定到我的视图模型中的属性。 (使用此场景纯粹用于学习/演示。)
我有一个名为 Item
的简单 DataModel,但在本示例中几乎没有相关性。
class Item : INotifyPropertyChanged
// Fields...
private bool _IsRequired;
private string _ItemName;
还有一个相当简单的视图模型,名为 ItemViewModel。
class ItemViewModel : INotifyPropertyChanged
private ObservableCollection<Item> _Items;
private bool _IsCheckBoxChecked;
private bool _IsCheckBoxVisible;
public ObservableCollection<Item> Items
get return _Items;
set _Items = value;
public bool IsCheckBoxChecked
get return _IsCheckBoxChecked;
set
if (_IsCheckBoxChecked == value)
return;
_IsCheckBoxChecked = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("IsCheckBoxChecked"));
PropertyChanged(this, new PropertyChangedEventArgs("IsCheckBoxVisible"));
public bool IsCheckBoxVisible
get return !_IsCheckBoxChecked;
set
if (_IsCheckBoxVisible == value)
return;
_IsCheckBoxVisible = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("IsCheckBoxVisible"));
(为简洁起见,省略了构造函数和INotifyPropertyChanged
实现。)
MainPage.xaml 中的控件布局如下。
<Window.Resources>
<local:VisibilityConverter x:Key="VisibilityConverter"/>
</Window.Resources>
<Window.DataContext>
<local:ItemViewModel/>
</Window.DataContext>
<Grid>
<StackPanel>
<CheckBox x:Name="checkBox" Content="Hide CheckBoxes" FontSize="14" IsChecked="Binding IsCheckBoxChecked, Mode=TwoWay" />
<ListView ItemsSource="Binding Items" HorizontalContentAlignment="Stretch" >
<ListView.ItemTemplate >
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="Binding ItemName"/>
<CheckBox Grid.Column="1" Visibility="Binding IsCheckBoxVisible, Converter=StaticResource VisibilityConverter" >
<CheckBox.DataContext>
<local:ItemViewModel/>
</CheckBox.DataContext>
</CheckBox>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<StackPanel Orientation="Horizontal" Margin="4,4,0,0">
<TextBlock Text="IsCheckBoxVisible:"/>
<TextBlock Text="Binding IsCheckBoxVisible" Margin="4,0,0,0" FontWeight="Bold" />
</StackPanel >
<Button Content="Button" Visibility="Binding IsCheckBoxVisible, Converter=StaticResource VisibilityConverter" Margin="4,4,4,4"/>
</StackPanel>
</Grid>
“隐藏复选框”复选框绑定到IsCheckBoxChecked
,用于更新IsCheckBoxVisible
。我还在DataTemplate
下方添加了几个额外的控件,以证明(对我自己)一切正常。)
我还实现了 Jeff Wilcox 的值转换器。 (谢谢。)http://www.jeff.wilcox.name/2008/07/visibility-type-converter/
当我运行应用程序时,选中和取消选中“隐藏复选框”,DataTemplate
函数之外的控件按预期进行,但是,唉,数据模板内的Checkbox
保持不变。
我已经成功了:
IsVisible="Binding IsChecked, Converter=StaticResource VisibilityConverter, ElementName=checkBox"
但我不只是在尝试模仿另一个控件,而是根据一个值做出决定。
非常感谢您提供的任何帮助或建议。
谢谢。
【问题讨论】:
在 Visual Studio 的调试输出窗口中是否出现任何绑定错误?它们通常很好地表明出了什么问题。 克里斯。感谢您的回复。检查了输出窗口,正如您所怀疑的,有错误。它无法“找到”IsCheckBoxVisible。根据下面邓肯的回复应用了修复,现在一切都很好。谢谢。 这能回答你的问题吗? Binding to viewmodel from inside a datatemplate 【参考方案1】:当您在 DataTemplate 中时,您的 DataContext 是数据模板对象,在本例中为 Item
。因此,DataTemplate 中 CheckBox 的 DataContext 是 Item
,而不是您的 ItemViewModel
。您可以通过<TextBlock Text="Binding ItemName"/>
看到这一点,它绑定到Item
类的一个属性。与 IsCheckBoxVisible 的绑定正在尝试在 Item
上查找名为 IsCheckBoxVisible 的属性。
有几种方法可以解决这个问题,但到目前为止最简单的是这样做:
在您的窗口上(在 xaml 中),输入它和 x:Name。例如:
<Window [...blah blah...]
x:Name="MyWindow">
将您的绑定更改为如下所示:
<CheckBox Grid.Column="1"
Visibility="Binding DataContext.IsCheckBoxVisible, ElementName=MyWindow, Converter=StaticResource VisibilityConverter">
我们使用 Window 作为 Binding 的源,然后查看它的 DataContext 属性(应该是您的 ItemViewModel
,然后关闭 IsCheckBoxVisible 属性。
如果您想要更高级的东西,另一种选择是使用代理对象来引用您的 DataContext。见this article on DataContextProxy。
【讨论】:
邓肯。感谢您的及时答复。我已经尝试过你的建议,它就像一个魅力。我认为为复选框添加一个单独的<CheckBox.DataContext><local:ItemViewModel/></...>
的路线:如果是这样,它不起作用的原因是当你在 xaml 中定义 ItemViewModel 就像你 创建 一个,所以你' d 有不同的实例。您可以解决这个问题,但我描述的解决方案更好。以上是关于绑定到 DataTemplate 中的视图模型属性的主要内容,如果未能解决你的问题,请参考以下文章
如何将 ObservableCollection 绑定到 DataTemplate 中的文本框?
用于视图模型的具有多个 DataTemplate 的 ItemsControl
WPF 在 GridViewColumn.CellTemplate 的 DataTemplate 中绑定 UserControl 属性