2012-12-05 159 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