WPF TreeView Material Design 数据双向绑定

利用Prism 搭建的一个WPF MVVM框架,导入了Material Design UI库,在实现TreeView时费了点周折,记录于此。

Xaml的写法如下:

需要应用命名空间:

 xmlns:domain="clr-namespace:management.wpfUI.Models"       
             xmlns:md="http://materialdesigninxaml.net/winfx/xaml/themes"
             xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

<TreeView  x:Name="treeView"   Grid.Row="0"  Foreground="White"   ItemsSource="{Binding NavMenus}"    MinWidth="220">
            <TreeView.Resources>
                <HierarchicalDataTemplate DataType="{x:Type domain:NavMenuModel}"   ItemsSource="{Binding ChildMenus}">
                    <TextBlock Text="{Binding MenuName}" Margin="3 2" />
                </HierarchicalDataTemplate>
                <DataTemplate DataType="{x:Type domain:MenuModel}">
                    <TextBlock  Text="{Binding MenuName}"  Margin="3 2"   />
                </DataTemplate>
            </TreeView.Resources>
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="SelectedItemChanged">
                    <i:InvokeCommandAction Command="{Binding SelectItemChangeCommand}" CommandParameter="{Binding ElementName=treeView,Path=SelectedItem}"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </TreeView>       

绑定的数据源对象定义如下:

 public class NavMenuModel:MenuModel
    {
        public NavMenuModel()
        {
            ChildMenus = new ObservableCollection<MenuModel>();
        }
        public ObservableCollection<MenuModel> ChildMenus { get; }
    }
    public class MenuModel
    {
        public int Id { get; set; }

        public int ParentId { get; set; }

        public string MenuName { get; set; }
        public MenuModel()
        {
        }
        public MenuModel(int menuId,string menuName, int parentMenuId, params MenuModel[] subItems)
        {
            this.Id = menuId;
            this.MenuName = menuName;
            this.ParentId = parentMenuId;
        }
    }

ViewModel写法:

  public class LeftMenuViewModel: BindableBase
    {
        public ObservableCollection<NavMenuModel> NavMenus { get; }

        public ICommand SelectItemChangeCommand
        {
            get
            {
                return new BaseCommand<object>((param) =>
                {
                    if (param != null)
                    {
                        SelectedItem =  param as MenuModel;
                    }
                });
            }
        }
        public LeftMenuViewModel()
        {
            NavMenus = new ObservableCollection<NavMenuModel>();
            var menu = new NavMenuModel() {  Id = 1,  MenuName = "Chapter 1" };
            
            var subMenu = new NavMenuModel() { Id = 11, MenuName = "Chapter 1.1", ParentId = 1 };
            subMenu.ChildMenus.Add(new MenuModel() { Id=111, MenuName="Chapter 1.1.1", ParentId= 11 });
            menu.ChildMenus.Add(subMenu);

            NavMenus.Add(menu);
            var m2 = new NavMenuModel() { Id = 2, MenuName = "Chapter 2" };

            var subMenu2 = new NavMenuModel() { Id = 21, MenuName = "Chapter 2.1", ParentId =1 };
         
            m2.ChildMenus.Add(subMenu2);
            NavMenus.Add(m2);
            NavMenus.Add(new NavMenuModel() { Id = 3, MenuName = "Chapter 3" });

            
        }
        private MenuModel _selectedItem;
        public MenuModel SelectedItem
        {
            get { return _selectedItem; }
            set { SetProperty(ref _selectedItem, value); }
        }

    }

实现的效果如下: 

  

开发过程中需要注意1:DataType="{x:Type domain:MenuModel}" 不能为同一个对象,利用继承来规避此问题,否则报错:

注意2:HierarchicalDataTemplate 的ItemSource 绑定层级关系和 TreeView挂载的ItemSource不同;

注意3:SelectItem引用父类型对象,避免null发生;

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值