2012-12-05 53 views
1

我有以下xaml;更新DataTemplate中DataTemplate的绑定

<DataTemplate DataType="{x:Type NameSpace:Node}"> 
     <StackPanel Orientation="Horizontal"> 
      <TextBlock Text="{Binding Item.Value}"/> 
      <ContentControl Content="{Binding Item}"/> 
     </StackPanel> 
    </DataTemplate> 

    <DataTemplate DataType="{x:Type NameSpace:Item}"> 
     <TextBlock Text="{Binding Value}" /> 
    </DataTemplate> 

当我使用Node模板来显示节点对象时,我得到两个TextBlocks,它们都显示相同的值。到现在为止还挺好。项目更改时发生此问题。当Node类触发INotifyPropertyChanged事件时,Node DataTemplate中的TextBlock会按预期更新,但Item DataTemplate中的TextBlock不会更新。

当Node类触发IPropertyChanged事件时,如何获取Item DataTemplate以更新其绑定?

更新 事实证明,上述工作适用于以下简单场景;

的XAML

 <DataTemplate DataType="{x:Type DataTemplateExample:Node}"> 
      <StackPanel Orientation="Horizontal"> 
       <TextBlock Text="{Binding Item.Value}"/> 
       <ContentControl Content="{Binding Item}"/> 
      </StackPanel> 
     </DataTemplate> 

     <DataTemplate DataType="{x:Type DataTemplateExample:Item}"> 
      <TextBlock Text="{Binding Value}" /> 
     </DataTemplate> 
    </Window.Resources> 

    <Grid> 
     <StackPanel Orientation="Vertical"> 
      <ContentControl Content="{Binding MyNode}"/> 
      <Button Command="{Binding ChangeMyNodeItem}">Change Item</Button> 
     </StackPanel> 
    </Grid> 
</Window> 

C#

public class MainViewModel 
{ 
    private readonly Node myNode; 
    private readonly DelegateCommand changeMyNodeItemCmd; 

    public MainViewModel() 
    { 
     myNode = new Node {Item = new Item("a")}; 
     changeMyNodeItemCmd = new DelegateCommand(()=> 
      myNode.Item = new Item("b")); 
    } 

    public Node MyNode { get { return myNode; } } 

    public ICommand ChangeMyNodeItem 
    { 
     get { return changeMyNodeItemCmd; } 
    } 
} 

public class Node : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    private Item item; 
    public Item Item 
    { 
     set 
     { 
      item = value; 
      if (PropertyChanged != null) 
       PropertyChanged(this,new PropertyChangedEventArgs("Item")); 
     } 
     get { return item; } 
    } 
} 

public class Item 
{ 
    private readonly string value; 

    public Item(string value) 
    { 
     this.value = value; 
    } 

    public string Value 
    { 
     get { return value; } 
    } 
} 

在我真实的情景我使用代理服务器,我想这是什么让WPF困惑。项目实际上并没有改变 - 它被重新映射。

最终我使用类似于ShadeOfGray提出的解决方案来解决问题。但我应该指出,除非您使用代理,否则这不是必需的。

+0

我假设你已经为了看到价值变动INotifyPropertyChanged的离子你的项目类。你是否也在你的节点类上实现INotifyPropertyChanged?如果不是,则ContentControl将保持绑定到旧项目。 – AlSki

+0

在Item属性更改时,我在Node类中实现了INotifyPropertyChanged。我没有在我的Item类中实现INotifyPropertyChanged,因为这个类是不可变的。对于特定的Item实例,Value属性不会改变。它是可变的节点类,我希望在重新分配Node.Item时更新UI。 – knick

回答

2

从你发布的内容我认为你在错误的类中解雇NotifyPropertyChanged。类似的东西应该在你的场景中正常工作。

根据评论更新时间:

public class Node : INotifyPropertyChanged 
{ 
    private Item item; 

    public event PropertyChangedEventHandler PropertyChanged; 

    public Item Item 
    { 
     get 
     { 
      return item; 
     } 

     set 
     { 
      item = value; 

      this.NotifyPropertyChanged("Item"); 

      if (item != null) 
      { 
       item.ForcePropertyChanged("Value"); 
      } 
     } 
    } 

    protected void NotifyPropertyChanged(string propertyName) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
} 

public class Item : INotifyPropertyChanged 
{ 
    private string itemValue; 

    public Item() 
    { 
     this.Value = string.Empty; 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    public string Value 
    { 
     get 
     { 
      return itemValue; 
     } 

     set 
     { 
      itemValue = value; 

      NotifyPropertyChanged("Value"); 
     } 
    } 

    public void ForcePropertyChanged(string propertyName) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 

    protected void NotifyPropertyChanged(string propertyName) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
} 
+0

感谢您的回应。您发布的代码覆盖了Value属性直接更改的场景...例如:'myNode.Item.Value = newValue;'我感兴趣的场景是通过重新分配父项来间接更改值。 。例如:'myNode.Item = new Item {Value = newValue};' – knick

+0

是的,这改变了一些东西:)。我已经更新了我的答案。 – ShadeOfGrey

+0

是的,看起来像一个潜在的解决方案 - 谢谢!我希望WPF可能已经足够聪明来为我处理这个问题,但如果在xaml中没有办法做到这一点,我会使用这个解决方案。我的物品类实际上是不可变的,所以让它触发INotifyPropertyChanged事件感觉不太正确。 – knick