2013-04-01 98 views
7

我对XAML相当陌生,但喜欢学习它。我真正努力的是将一个属性绑定到DataTemplate中的一个元素。XAML:绑定DataTemplate中的属性

我已经创建了一个简单的WPF示例来(希望)解释我的问题。

我这个例子我试图将中CheckBoxVisibility属性绑定到我的viewmodel中的属性。 (纯粹用于学习/演示使用此场景。)

我有一个简单的DataModel,名称为Item,但在此示例中没有多大关联。

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}" 

但我不只是试图模仿另一个控制,但要根据价值决定。

我会真正感谢您可以提供的任何帮助或建议。

谢谢。

+0

在Visual Studio的调试输出窗口中是否有任何绑定错误?他们通常很好地指出发生了什么问题。 – ChrisF

+0

克里斯。感谢您的回应。检查输出窗口,并且,如您所怀疑的那样,出现错误。它无法'找到'IsCheckBoxVisible。根据Duncan的回复,下面的应用修复,现在一切正常。谢谢。 – Dowse

回答

15

当您在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}}"> 

我们使用窗口作为源绑定,然后看着它的DataContext属性(这应该是你的ItemViewModel,然后脱下IsCheckBoxVisible财产。

另一种选择,如果你想要的东西票友,是使用代理对象引用您的DataContext。见this article on DataContextProxy

+1

邓肯。感谢您的及时答复。我已经尝试了你的建议,它的功能就像一个魅力。我认为添加一个单独的标签的复选框将工作,但唉,不。再次感谢你。在给你提供的链接中也会给Dan Wahlin的atricle一个阅读。 (我试着投票回答你的答案,但是我的低声誉阻止我这样做。) – Dowse

+0

很高兴我能帮上忙! :-)这并不完全相关,但从您的评论中可以看出:手动设置元素的DataContext(除了Window或其他根目录)是您想要非常小心的事情,并且通常表明您'做错了事。我想象你的尝试是沿着'行的:如果是这样,它不起作用的原因是当你在xaml中定义ItemViewModel时,就像* *一个,所以你会有一个不同的实例。你可以解决这个问题,但我描述的解决方案更好。 –

相关问题