摘要:采用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>
二、效果