我对XAML很新,但很乐意学习它。我真正挣扎的是将属性绑定到DataTemplate
中的元素。
我创建了一个简单的WPF示例,(希望)解释了我的问题。
我在这个示例中尝试将Visibility
中CheckBox
的{{1}}属性绑定到我的viewmodel中的属性。 (仅将此场景用于学习/演示。)
我有一个名为DataTemplate
的简单DataModel,但在此示例中没什么关系。
Item
一个名为ItemViewModel的相当简单的视图模型。
class Item : INotifyPropertyChanged
{
// Fields...
private bool _IsRequired;
private string _ItemName;
(为简洁起见,省略了构造函数和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"));
}
实现。)
MainPage.xaml中的控件如下所示。
INotifyPropertyChanged
隐藏CheckBoxes&#39;复选框绑定到<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
下面添加了一些额外的控件来证明(对我自己)一切正常。)
我还实施了Jeff Wilcox的价值转换器。 (谢谢。)http://www.jeff.wilcox.name/2008/07/visibility-type-converter/
当我运行应用时,检查并取消选中“隐藏复选框”,按预期在DataTemplate
功能外控制,但是,唉,数据模板内的DataTemplate
保持不变
我取得了成功:
Checkbox
但我不只是尝试模仿另一个控件,而是根据一个值做出决定。
我真的非常感谢您提供的任何帮助或建议。
谢谢。
答案 0 :(得分:19)
当您在DataTemplate中时,您的DataContext是数据模板化对象,在本例中为Item
。因此,DataTemplate中CheckBox的DataContext是Item
,而不是ItemViewModel
。你可以通过<TextBlock Text="{Binding ItemName}"/>
看到这个,它绑定到Item
类的属性。绑定到IsCheckBoxVisible正试图在Item
上找到一个名为IsCheckBoxVisible的属性。
有很多方法可以解决这个问题,但到目前为止最简单的方法是:
在你的窗口(在xaml中),给它和x:名字。例如:
<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。