2009-12-07 69 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会不会更容易?