2009-12-07 28 views
1

我有一個TreeViewItemsSource設置爲我有一個模型。深度3級是一個對象,它的狀態可以改變,而不是爲每個階段編寫一個View和ViewModel(非常冗長的業務),我只想用代碼更新它。使用代碼更新TreeViewItem的綁定? (XAML/WPF)

因此,基本上我有一個事件,一旦我的模型更新被觸發,我趕上它然後找到與此位數據相關的TreeViewItem。我現在的問題是我不知道如何更新它的綁定來反映新的價值!

任何人都可以幫忙嗎?

我知道這不是最佳實踐,但我真的不想浪費時間編寫大量代碼來更新一件事。

感謝 克里斯

+0

儘管在你的問題中,你明確指出你想在代碼中這樣做,這只是爲了實現的速度,因爲xaml的做法很簡短? – Andrew 2009-12-07 19:51:31

回答

0

這個例子有效,儘管它只有兩層(不是3層)。它顯示了帶有父項A,B和C以及編號子項(A.1,B.1等)的簡單2級分層樹視圖。當單擊重命名B.1按鈕時,它將B.1重命名爲「Sylvia」。

using System.Collections.Generic; 
using System.Windows; 
using System.Windows.Controls; 

namespace UpdateVanillaBindingValue 
{ 
    /// <summary> 
    /// Interaction logic for Window1.xaml 
    /// </summary> 
    public partial class Window1 : Window 
    { 
     private DataClass _data; 

     public Window1() 
     { 
      InitializeComponent(); 
      var data = CreateData(); 
      DataContext = _data = data; 
     } 

     private DataClass CreateData() 
     { 
      return new DataClass 
       { 
        Parents=new List<Parent> 
         { 
          new Parent{Name="A",Children=new List<Child>{new Child{Name="A.0"},new Child{Name="A.1"}}}, 
          new Parent{Name="B",Children=new List<Child>{new Child{Name="B.0"},new Child{Name="B.1"},new Child{Name="B.2"}}}, 
          new Parent{Name="C",Children=new List<Child>{new Child{Name="C.0"},new Child{Name="C.1"}}} 
         } 
       }; 
     } 

     private void Rename_Click(object sender, RoutedEventArgs e) 
     { 
      var parentB = _data.Parents[1]; 
      var parentBItem = TheTree.ItemContainerGenerator.ContainerFromItem(parentB) as TreeViewItem; 
      parentB.Children[1].Name = "Sylvia"; 

      var parentBItemsSource = parentBItem.ItemsSource; 
      parentBItem.ItemsSource = null; 
      parentBItem.ItemsSource = parentBItemsSource; 
     } 
    } 

    public class DataClass 
    { 
     public List<Parent> Parents { get; set; } 
    } 

    public class Parent 
    { 
     public string Name { get; set; } 
     public List<Child> Children { get; set; } 
    } 

    public class Child 
    { 
     public string Name { get; set; } 
    } 
} 

<Window x:Class="UpdateVanillaBindingValue.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Window1" Height="300" Width="300"> 
    <Grid> 
     <Grid.Resources> 
      <DataTemplate x:Key="ChildTemplate"> 
       <TextBlock Margin="50,0,0,0" Text="{Binding Name}" /> 
      </DataTemplate> 
      <HierarchicalDataTemplate x:Key="ParentTemplate" ItemsSource="{Binding Children}" ItemTemplate="{StaticResource ChildTemplate}"> 
       <TextBlock Text="{Binding Name}" /> 
      </HierarchicalDataTemplate> 
     </Grid.Resources> 
     <TreeView x:Name="TheTree" ItemsSource="{Binding Parents}" ItemTemplate="{StaticResource ParentTemplate}" /> 
     <Button VerticalAlignment="Bottom" HorizontalAlignment="Center" Content="Rename B.1" Click="Rename_Click" /> 
    </Grid> 
</Window> 

這是一個黑客攻擊,但它每次更新ItemsSource屬性時都會重新評估DataTemplate。

理想情況下,您將在您的模型對象類上實現此TreeViewItem綁定的INotifyPropertyChanged,並在該值發生更改時觸發PropertyChanged事件。事實上,你應該小心,因爲它不會導致內存泄漏:Finding memory-leaks in WPF Applications

+0

謝謝,我已經嘗試過這一點,只有當我對整個樹視圖執行操作時,它才能在treeitem級別上工作,這意味着我失去了我選擇的項目 – Chris 2009-12-08 09:00:40

+0

嘗試修改後的示例 - 它適用於我的機器;-)關鍵是循環父TreeViewItem上的ItemsSource而不是TreeView上的DataContext。 – 2009-12-08 18:14:29

0

聽起來像是你可能需要採取看看UpdateSourceUpdateTarget方法。

MSDN reference for UpdateSource

雖然我不能完全肯定,這時候,你實際上已經綁定的TreeView的ItemSource的分層數據結構的工作,但它是在那裏我會開始調查。

1

您確定在相關類上實現INotifyPropertyChanged會不會更容易?