wpf 绑定到 DataTemplate 中的视图模型属性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15748578/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Binding to a viewmodel property in a DataTemplate
提问by Dowse
I'm fairly new to XAML but enjoying learning it. The thing I'm really struggling with is binding a property to an element in a DataTemplate
.
我对 XAML 还很陌生,但很喜欢学习它。我真正挣扎的事情是将属性绑定到DataTemplate
.
I have created a simple WPF example to, (hopefully,) explain my problem.
我创建了一个简单的 WPF 示例来(希望)解释我的问题。
I this example I am trying to bind the Visibility
property of a CheckBox
in a DataTemplate
to a Property in my viewmodel. (Using this scenario purely for learning/demo.)
在这个例子中,我试图将Visibility
aCheckBox
中的属性绑定DataTemplate
到我的视图模型中的属性。(使用这个场景纯粹是为了学习/演示。)
I have a simple DataModel named Item
, but is of little relevance in this example.
我有一个名为 的简单数据模型Item
,但与本示例无关。
class Item : INotifyPropertyChanged
{
// Fields...
private bool _IsRequired;
private string _ItemName;
And a fairly simple View Model named ItemViewModel.
还有一个相当简单的视图模型,名为 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"));
}
(Constructors and INotifyPropertyChanged
implementation omitted for brevity.)
(INotifyPropertyChanged
为简洁起见,省略了构造函数和实现。)
Controls laid out in MainPage.xaml as follows.
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>
The 'Hide CheckBoxes' checkbox is bound to IsCheckBoxChecked
and is used to update IsCheckBoxVisible
. I've also added a couple of extra controls below the DataTemplate
to prove, (to myself,) the everything works.)
“隐藏复选框”复选框绑定到IsCheckBoxChecked
并用于更新IsCheckBoxVisible
. 我还在下面添加了一些额外的控件DataTemplate
来证明(对我自己)一切正常。)
I have also implemented Jeff Wilcox's value converter. (Thank you.) http://www.jeff.wilcox.name/2008/07/visibility-type-converter/
我还实现了 Jeff Wilcox 的值转换器。(谢谢。)http://www.jeff.wilcox.name/2008/07/visibility-type-converter/
When I run the app, checking and unchecking the 'Hide Checkbox', controls outside the DataTemplate
function as expected but, alas, the Checkbox
inside the data template remains unchanged.
当我运行应用程序时,选中和取消选中“隐藏复选框”,DataTemplate
按预期控制功能外部,但是,唉,Checkbox
内部数据模板保持不变。
I have had success with:
我在以下方面取得了成功:
IsVisible="{Binding IsChecked, Converter={StaticResource VisibilityConverter}, ElementName=checkBox}"
But I'm not just trying mimic another control but make decisions based on a value.
但我不只是试图模仿另一个控件,而是根据一个值做出决定。
I would REALLY appreciate any help or advice you can offer.
我真的很感激你能提供的任何帮助或建议。
Thank you.
谢谢你。
回答by Duncan Matheson
When you are in a DataTemplate, your DataContext is the data templated object, in this case an Item
. Thus, the DataContext of the CheckBox in the DataTemplate is an Item
, not your ItemViewModel
. You can see this by your <TextBlock Text="{Binding ItemName}"/>
, which binds to a property on the Item
class. The Binding to IsCheckBoxVisible is trying to find a property called IsCheckBoxVisible on Item
.
当您在 DataTemplate 中时,您的 DataContext 是数据模板化对象,在本例中为Item
. 因此,DataTemplate 中 CheckBox 的 DataContext 是一个Item
,而不是您的ItemViewModel
. 您可以通过您的 看到这一点<TextBlock Text="{Binding ItemName}"/>
,它绑定到Item
类上的一个属性。绑定到 IsCheckBoxVisible 正在尝试在 上查找名为 IsCheckBoxVisible 的属性Item
。
There are a couple of ways around this, but by far the easiest is to do this:
有几种方法可以解决这个问题,但到目前为止最简单的是这样做:
On your Window (in the xaml), give it and x:Name. Eg:
在您的窗口(在 xaml 中)上,给它和 x:Name。例如:
<Window [...blah blah...]
x:Name="MyWindow">
Change your binding to look like this:
将您的绑定更改为如下所示:
<CheckBox Grid.Column="1"
Visibility="{Binding DataContext.IsCheckBoxVisible, ElementName=MyWindow, Converter={StaticResource VisibilityConverter}}">
We're using the Window as the source for the Binding, then looking at its DataContext property (which should be your ItemViewModel
, and then pulling off the IsCheckBoxVisible property.
我们使用 Window 作为 Binding 的源,然后查看其 DataContext 属性(应该是您的ItemViewModel
,然后取消 IsCheckBoxVisible 属性。
Another option, if you want something fancier, is to use a proxy object to reference your DataContext. See this article on DataContextProxy.
如果您想要更高级的东西,另一种选择是使用代理对象来引用您的 DataContext。请参阅有关 DataContextProxy 的这篇文章。