天天看点

mvvm menu 绑定

苦苦研究了好长时间,终于搞定mvvm 框架下的 menu 绑定,包括二层和三层MenuItem及其Header、Command和 CommandParameter的绑定,真是好难。

主程序 MainViewModel.cs

public class MainViewModel : ViewModelBase
    {
        public RelayCommand LoginCommand { get; set; }
        public RelayCommand LogoutCommand { get; set; }
        public RelayCommand AboutCommand { get; set; }
        public RelayCommand QuitWindowCommand { get; set; }
        public RelayCommand NewWindowCommand { get; set; }

        public RootMenuViewModel TheMenuA { get; set; }
        public RootMenuViewModel TheMenuB { get; set; }


        public MainViewModel()
        {
            LoginCommand = new RelayCommand(DoLogin);
            AboutCommand = new RelayCommand(DoAbout);
            LogoutCommand = new RelayCommand(DoLogout, CanDoLogout);
            NewWindowCommand = new RelayCommand(DoNewWindow, CanDoNewWindow);
            QuitWindowCommand = new RelayCommand(DoQuit);

            TheMenuA = GetMenusA();
            TheMenuB = GetMenusB();
            TheMenuC = GetMenusC();
        }

        private RootMenuViewModel GetMenusA()
        {
            RootMenu RootMenuA = new RootMenu("文件");
            RootMenuA.MenuItems = new List<MenuItem>();
	    MenuItem menuItemA = new MenuItem("新建");
	    menuItemA.Childs.Add(new ChildItem(menuItemA, "新建1", 1, NewWindowCommand));
	    menuItemA.Childs.Add(new ChildItem(menuItemA, "新建2", 2, NewWindowCommand));
            RootMenuA.MenuItems.Add(menuItemA);
            RootMenuA.MenuItems.Add(new MenuItem(""));
            RootMenuA.MenuItems.Add(new MenuItem("退出登录", LogoutCommand));
            RootMenuA.MenuItems.Add(new MenuItem("Separator"));
            RootMenuA.MenuItems.Add(new MenuItem("退出系统", QuitWindowCommand));

            RootMenuViewModel rootMenuViewModel = new RootMenuViewModel(RootMenuA);

            return rootMenuViewModel;
        }
        private RootMenuViewModel GetMenusB()
        {
            ObservableCollection<MenuUseXklx> MenuUseXklx1 = MyApp.DataAccess.GetUseXklxList();
            RootMenu RootMenuA = new RootMenu("帮助");
            RootMenuA.MenuItems = new List<MenuItem>();
            RootMenuA.MenuItems.Add(new MenuItem("关于", AboutCommand));

            RootMenuViewModel rootMenuViewModel = new RootMenuViewModel(RootMenuA);

            return rootMenuViewModel;
        }
        //相关命令略
}
           

相关菜单类字段属性:

public class RootMenu
    {
        public string RootName { get; set; }
        public RelayCommand Command { get; set; }
        public List<MenuItem> MenuItems { get; set; }
        public RootMenu(string rootName) { RootName = rootName; }
    }
    public class MenuItem
    {
        public string MenuItemName { get; set; }
        public RelayCommand Command { get; set; }
        public List<ChildItem> Childs { get; set; }
        public MenuItem(string menuName, RelayCommand command) { MenuItemName = menuName; Command = command; }
        public MenuItem(string menuName) { MenuItemName = menuName; }
        public MenuItem() { }

    }
    public class ChildItem
    {
        
        public string ChildName { get; set; }
        public short Childlx { get; set; }
        public RelayCommand Command { get; set; }
        public MenuItem MenuItem { get; set; }
        public ChildItem(MenuItem menuClass, string childName, short childlx, RelayCommand command) { MenuItem = menuClass; ChildName = childName; Childlx = childlx; Command = command; }
        public ChildItem() { }

    }
    public class SeparatorViewModel : MenuItemViewModel
    {
        public SeparatorViewModel(MenuItemViewModel parentViewModel)
            : base(parentViewModel)
        {

        }
    }
           

转换类基类:(ViewModelBase代码略)

public class MenuItemViewModel : ViewModelBase
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="MenuItemViewModel"/> class.
        /// </summary>
        /// <param name="parentViewModel">The parent view model.</param>
        public MenuItemViewModel(MenuItemViewModel parentViewModel)
        {
            ParentViewModel = parentViewModel;
            _childMenuItems = new ObservableCollection<MenuItemViewModel>();
        }

        private ObservableCollection<MenuItemViewModel> _childMenuItems;
        /// <summary>
        /// Gets the child menu items.
        /// </summary>
        /// <value>The child menu items.</value>
        public ObservableCollection<MenuItemViewModel> Children
        {
            get
            {
                return _childMenuItems;
            }
        }

        private string _header;
        /// <summary>
        /// Gets or sets the header.
        /// </summary>
        /// <value>The header.</value>
        public string Header
        {
            get
            {
                return _header;
            }
            set
            {
                _header = value; RaisePropertyChanged("Header");
            }
        }
        private short _childlx;
        /// <summary>
        /// Gets or sets the CommandParameter.
        /// </summary>
        /// <value>The CommandParameter.</value>
        public short Childlx
        {
            get
            {
                return _childlx;
            }
            set
            {
                _childlx = value; RaisePropertyChanged("Childlx");
            }
        }
        /// <summary>
        /// Gets or sets the Command.
        /// </summary>
        /// <value>The Command.</value>
        private RelayCommand command;
        public RelayCommand Command
        {
            get
            {
                return command;
            }
            set
            {
                command = value; RaisePropertyChanged("Command");
            }
        }

        /// <summary>
        /// Gets or sets the parent view model.
        /// </summary>
        /// <value>The parent view model.</value>
        public MenuItemViewModel ParentViewModel { get; set; }

        public virtual void LoadChildMenuItems()
        {

        }
           

Root菜单类:

public class RootMenuViewModel : MenuItemViewModel
    {
        private RootMenu _rootMenu;

        /// <summary>
        /// Initializes a new instance of the <see cref="MenuItemViewModel"></see> class.
        /// </summary>
        /// <param name="parentViewModel">The parent view model.</param>
        public RootMenuViewModel(RootMenu rootMenu)
            : base(null)
        {
            _rootMenu = rootMenu;
            base.Header = RootName;
            base.Command = RootCommand;
            if (_rootMenu.MenuItems != null)
            LoadChildMenuItems();
        }
        public string RootName
        {
            get
            {
                return _rootMenu.RootName;
            }
            set
            {
                _rootMenu.RootName = value; RaisePropertyChanged("RootName");
            }
        }
        public RelayCommand RootCommand
        {
            get
            {
                return _rootMenu.Command;
            }
            set
            {
                _rootMenu.Command = value; RaisePropertyChanged("RootCommand");
            }
        }
        /// <summary>
        /// Loads the child menu items.
        /// </summary>
        public override void LoadChildMenuItems()
        {
            _rootMenu.MenuItems.ForEach
                (
                        MenuItem => 
                        {
                            if (MenuItem.MenuItemName == string.Empty || MenuItem.MenuItemName == "Separator")
                            {
                                SeparatorViewModel separatorViewModel = new SeparatorViewModel(this);
                                Children.Add(separatorViewModel);
                            }
                            else if (MenuItem.MenuItemName != null)
                            {
                                MenuClassViewModel childMenuViewModel = new MenuClassViewModel(this, MenuItem);
                                childMenuViewModel.Header = MenuItem.MenuItemName;
                                childMenuViewModel.Command = MenuItem.Command;
                                Children.Add(childMenuViewModel);
                            }
                        }
                );
        }
           

子菜单类:

public class MenuClassViewModel : MenuItemViewModel
    {
        private MenuItem _menuClass;
        /// <summary>
        /// Initializes a new instance of the <see cref="MenuItemViewModel"></see> class.
        /// </summary>
        /// <param name="parentViewModel">The parent view model.</param>
        public MenuClassViewModel(RootMenuViewModel parentViewModel, MenuItem menuClass)
            : base(parentViewModel)
        {
            _menuClass = menuClass;
            if (_menuClass.Childs != null)
            LoadChildMenuItems();
        }

        //private string _menuName;
        /// <summary>
        /// Gets or sets the name of the team.
        /// </summary>
        /// <value>The name of the team.</value>
        public string MenuName
        {
            get
            {
                return _menuClass.MenuItemName;
            }
            set
            {
                _menuClass.MenuItemName = value; RaisePropertyChanged("MenuName");
            }
        }
        public RelayCommand ItemCommand
        {
            get
            {
                return _menuClass.Command;
            }
            set
            {
                _menuClass.Command = value; RaisePropertyChanged("ItemCommand");
            }
        }


        public override void LoadChildMenuItems()
        {
            _menuClass.Childs.ForEach(child =>
                            {
                                if (child.ChildName == string.Empty)
                                {
                                    SeparatorViewModel separatorViewModel = new SeparatorViewModel(this);
                                    Children.Add(separatorViewModel);
                                }
                                else
                                { 
                                    ChildMenuViewModel childViewModel = new ChildMenuViewModel(this, child);
                                    childViewModel.Header = child.ChildName;
                                    childViewModel.Childlx = child.Childlx;
                                    childViewModel.Command = child.Command;
                                    Children.Add(childViewModel);
                                }
                            });
        }
    }
           

三层菜单类:

class ChildMenuViewModel : MenuItemViewModel
    {
        private ChildItem _child;
        /// <summary>
        /// Initializes a new instance of the <see cref="MenuItemViewModel"></see> class.
        /// </summary>
        /// <param name="parentViewModel">The parent view model.</param>
        public ChildMenuViewModel(MenuClassViewModel parentViewModel, ChildItem child)
            : base(parentViewModel)
        {
            _child = child;
        }


        public string ChildName
        {
            get
            {
                return _child.ChildName;
            }
            set
            {
                _child.ChildName = value; RaisePropertyChanged("ChildName");
            }
        }
        public short ChildLx
        {
            get
            {
                return _child.Childlx;
            }
            set
            {
                _child.Childlx = value; RaisePropertyChanged("ChildLx");
            }
        }
        public RelayCommand ChildCommand
        {
            get
            {
                return _child.Command;
            }
            set
            {
                _child.Command = value; RaisePropertyChanged("ChildCommand");
            }
        }
    }
           

窗口代码:

<Window.Resources>
        <HierarchicalDataTemplate DataType="{x:Type vm:MenuItemViewModel}" ItemsSource="{Binding Children}">
            <MenuItem Header="{Binding Path=Header}" Command="{Binding Path=Command}" CommandParameter="{Binding Path=Childlx}"/>
        </HierarchicalDataTemplate>
        <DataTemplate DataType="{x:Type vm:SeparatorViewModel}">
            <Separator/>
        </DataTemplate>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="26*"/>
        </Grid.RowDefinitions>
        <StackPanel>
            <Menu TextBlock.FontSize="14">
                <MenuItem ItemsSource="{Binding TheMenuA.Children}" Header="{Binding TheMenuA.Header}"/>
                <MenuItem ItemsSource="{Binding TheMenuB.Children}" Header="{Binding TheMenuB.Header}"/>
            </Menu>
        </StackPanel>
    </Grid>