TreeView —WPF—MVVM—HierarchicalDataTemplate

Posted 苹果园dog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TreeView —WPF—MVVM—HierarchicalDataTemplate相关的知识,希望对你有一定的参考价值。

摘要:采用HierarchicalDataTemplate数据模板和treeview在MVVM模式下实现行政区划树,

支持勾选。勾选父节点,子节点回全部自动勾选;子节点部分勾选时,父节点半勾选;子节点全部勾选时,父节点勾选。反之亦然。

HierarchicalDataTemplate是分层数据模板,通常用于tree,menu等层级控件。

HierarchicalDataTemplate的ItemsSource属性绑定下一级数据源。
Model为行政区数据实体类,通常访问数据库获取数据并构建对象。
ViewModel为界面的抽象模型,表示界面的数据和行为,是Model和View的桥梁。

view就是界面。

一、代码

1、Model

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WpfHierarchicalTemplate
{
    public class District
    {
        public int ID { get; set; }
        public string   Xzqhdm { get; set; }//行政区划代码
        public string Xzqhmc { get; set; }//行政区划名称
        public int Level { get; set; }//级别,0全国,1省,2地市,3县,4,乡镇,5,村
        public IList<District> Children { get; set; }
        public District Parent { get; set; }
    }
}

  2、ViewModel

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.ObjectModel;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace WpfHierarchicalTemplate
{
    public class DistrictNodeViewModel : ModelCommon.NotifyObject
    {
        private bool? isSelected = false;

        public bool? IsSelected
        {
            get { return isSelected; }
            set
            {
                isSelected = value;
                RaisePropertyChanged("IsSelected");
            }
        }

        private bool? isChecked = false;

        public bool? IsChecked
        {
            get { return isChecked; }
            set
            {
                SetIsChecked(value);
            }
        }

        private void SetIsChecked(bool? value)
        {
            if (value != isChecked)
            {
                isChecked = value;
                RaisePropertyChanged("IsChecked");
            }
            if (this.Children.Count > 0 && this.Children[0].isChecked != value)
            {
                //设置子节点勾选状态
                foreach (var item in this.Children)
                {
                    if (value!=null)
                    {
                        item.IsChecked = value;
                    }                    
                }
            }
            if (this.parent != null)
            {
                if (this.Parent.Children.Count == this.Parent.Children.Count(item => item.isChecked == value))
                {
                    //同一级节点全部选中,则父节点选中。反之亦然。
                    this.Parent.IsChecked = value;
                }
                else if (this.Parent.Children.Count > this.Parent.Children.Count(item => item.isChecked == value))
                {
                    if (this.Parent.IsChecked!=null)
                    {
                        this.Parent.IsChecked = null;
                    }                    
                }                
            }

        }

        private bool? isExpand = false;

        public bool? IsExpand
        {
            get { return isExpand; }
            set
            {
                isExpand = value;
                RaisePropertyChanged("IsExpand");
            }
        }

        private BitmapImage img;

        public BitmapImage Img
        {
            get { return img; }
            set
            {
                img = value;
                RaisePropertyChanged("Img");
            }
        }

        private ObservableCollection<DistrictNodeViewModel> children = new ObservableCollection<DistrictNodeViewModel>();

        public ObservableCollection<DistrictNodeViewModel> Children
        {
            get { return children; }
            set
            {
                children = value;
                RaisePropertyChanged("Children");
            }
        }

        private DistrictNodeViewModel parent;

        public DistrictNodeViewModel Parent
        {
            get { return parent; }
            set
            {
                parent = value;
                RaisePropertyChanged("Parent");
            }
        }

        private District district;

        public District District
        {
            get { return district; }
            set
            {
                district = value;
                RaisePropertyChanged("District");
            }
        }
    }
}

 

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.ObjectModel;
namespace WpfHierarchicalTemplate
{
    public class DistrictMainViewModel : ModelCommon.NotifyObject
    {
        private ObservableCollection<DistrictNodeViewModel> vmNodes;

        public ObservableCollection<DistrictNodeViewModel> VmNodes
        {
            get { return vmNodes; }
            set
            {
                vmNodes = value;
                RaisePropertyChanged("VmNodes");
            }
        }

        public DistrictMainViewModel()
        {
            this.VmNodes = new ObservableCollection<DistrictNodeViewModel>
            {
                LoadData()
            };
        }
        public DistrictNodeViewModel LoadData()
        {
            ObservableCollection<District> rootNodes =new ObservableCollection<District>();
            District d00 = new District()
            {
                Xzqhmc = "全国",
                Parent = null
            };
            District d0 = new District()
            {
                 Xzqhmc="河南",
                   Parent=d00                  
            };

            District d1 = new District()
            {
                Xzqhmc = "北京",
                Parent = d00
            };

            District d2 = new District()
            {
                Xzqhmc = "山东",
                Parent = d00
            };
            District d11 = new District()
            {
                Xzqhmc = "海淀区",
                Parent = d1
            };
            District d12 = new District()
            {
                Xzqhmc = "石景山区",
                Parent = d1
            };
            District d13 = new District()
            {
                Xzqhmc = "朝阳区",
                Parent = d1
            };            

            District d01 = new District()
            {
                Xzqhmc = "商丘",
                Parent = d0
            };
            District d02 = new District()
            {
                Xzqhmc = "郑州",
                Parent = d0
            };
            District d03 = new District()
            {
                Xzqhmc = "周口",
                Parent = d0
            };
            d1.Children = new List<District> { d11, d12, d13 };
            d0.Children = new List<District> { d01, d02, d03 };
            d00.Children = new List<District>{d1,d2,d0};
            rootNodes.Add(d00);
            DistrictNodeViewModel dnv = new DistrictNodeViewModel();
            dnv.District = rootNodes[0];
            SetDNV(dnv, rootNodes[0]);
            return dnv;
        }

        private void SetDNV(DistrictNodeViewModel vm,District root)
        {
            if (root==null||root.Children==null||root.Children.Count==0)
            {
                return;
            }
            foreach (var item in root.Children)
            {
                DistrictNodeViewModel vmNew = new DistrictNodeViewModel();
                vmNew.District = item;
                vmNew.Parent = vm;
                vmNew.Img = new System.Windows.Media.Imaging.BitmapImage(new Uri("/dog.jpg", UriKind.Relative));
                vm.Children.Add(vmNew);
                SetDNV(vmNew, item);
            }
        }

    }
}

 

  3、主窗口

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfHierarchicalTemplate
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new DistrictMainViewModel();
        }
    }
}

  

4、前台xaml

<Window x:Class="WpfHierarchicalTemplate.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <HierarchicalDataTemplate x:Key="treeTemplate" ItemsSource="{Binding Children}">
            <StackPanel Orientation="Horizontal">
                <CheckBox IsChecked="{Binding IsChecked}"></CheckBox>
                <Image Source="{Binding Img}" Height="20" Width="16"></Image>
                <TextBlock Text="{Binding District.Xzqhmc}"></TextBlock>
            </StackPanel>
        </HierarchicalDataTemplate>
    </Window.Resources>
    <Grid>
        <TreeView  ItemTemplate="{StaticResource treeTemplate}" ItemsSource="{Binding VmNodes}">
        </TreeView>
    </Grid>
</Window>

 

  二、效果

以上是关于TreeView —WPF—MVVM—HierarchicalDataTemplate的主要内容,如果未能解决你的问题,请参考以下文章

WPF MVVM TreeView SelectedItem

WPF - MVVM Treeview获取所选项目[重复]

WPF - MVVM ???TreeView

WPF TreeView IsExpanded 绑定不上的问题

用户自定义TreeView控制双击冒泡事件WPF MVVM问题,怎么解决

WPF中TreeView的使用