文章使用的是MVVMLight框架,下载地址:http://mvvmlight.codeplex.com/
首先要对TreeView进行扩展,使得它能够有Command,里面需要用到Prism,下载地址:http://www.microsoft.com/en-us/download/details.aspx?displaylang=en&id=28950
参考文章:http://www.silverlightshow.net/items/Make-the-TreeView-control-to-be-MVVM-compliant.aspx
需要先添加引用:
1 xmlns:tree="clr-namespace:[your namespace]"
View代码:
1 <tree:TreeViewWithCommand ItemsSource="{Binding Root,Mode=TwoWay}" 2 tree:ItemExpanded.Command="{Binding ItemExpanded}" 3 tree:SelectedItemChanged.Command="{Binding ItemSelected}"> 4 <tree:TreeViewWithCommand.ItemTemplate> 5 <c:HierarchicalDataTemplate ItemsSource="{Binding Children,Mode=TwoWay}" > 6 <TextBlock Text="{Binding Current. Value,Mode=TwoWay}"></TextBlock> 7 </c:HierarchicalDataTemplate> 8 </tree:TreeViewWithCommand.ItemTemplate> 9 </tree:TreeViewWithCommand>
然后新增一个View用来存储TreeView的数据:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 public class Tree<T> 2 { 3 public ObservableCollection<Tree<T>> Children { get; set; } 4 public T Current { get; set; } 5 6 7 8 public Tree(T parent) 9 { 10 this.Current = parent; 11 this.Children = new ObservableCollection<Tree<T>>(); 12 } 13 14 public Tree(T parent, T child) 15 { 16 this.Current = parent; 17 this.Children = new ObservableCollection<Tree<T>>(); 18 this.Children.Add(new Tree<T>(child)); 19 } 20 21 22 }
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 public class Product 2 { 3 public int ProductId { get; set; } 4 public string ProductName { get; set; } 5 }
在ViewModel(记得继承ViewModelBase)中添加属性用来存放TreeView的数据:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 private ObservableCollection<Tree<Product>> _root; 2 public ObservableCollection<Tree<Product>> Root 3 { 4 get { return _root; } 5 private set 6 { 7 if (!ReferenceEquals(_root, value)) 8 { 9 _root = value; 10 RaisePropertyChanged("Root"); 11 12 } 13 14 } 15 }
先加载父级节点,对于每个节点添加loading子节点,那样展开节点时就会先显示loading节点,当获取到数据时再加载数据:
1 private void LoadData() 2 { 3 this.Root = new ObservableCollection<Tree<Product>>(); 4 Root.Add(new Tree<Product>(BuildLoadingChild())); 5 6 lstProduct = 获取数据; 7 8 this.Root.Clear(); 9 foreach (Product item in lstProduct ) 10 { 11 Root.Add(new Tree<Product>(item, BuildLoadingChild())); 12 13 } 14 } 15 16 private Product BuildLoadingChild() 17 { 18 return new Product() 19 { 20 ProductId = -999, 21 ProductName = "loading" 22 }; 23 }
展开节点时获取子节点,当然不能忘记先要把loading节点给删掉,先在ViewModel中定义RelayCommand:
1 private RelayCommand<Tree<Product>> _itemExpanded; 2 public RelayCommand<Tree<Product>> ItemExpanded 3 { 4 get 5 { 6 if (_itemExpanded == null) 7 { 8 _itemExpanded = new RelayCommand<Tree<Product>>(o => this.OnItemExpanded(o)); 9 } 10 return _itemExpanded; 11 } 12 }
展开事件:
1 private void OnItemExpanded(Tree<Product> item) 2 { 3 var lstChildren = 获取数据; 4 if (lstChildren == null || lstChildren.Count <= 0) 5 { 6 item.Children.Clear(); 7 return; 8 } 9 10 11 item.Children.Clear(); 12 foreach (Product i in lstChildren) 13 { 14 item.Children.Add(new Tree<Product>(i, BuildLoadingChild())); 15 } 16 }