带有绑定的MVVM菜单栏

时间:2019-02-28 11:55:40

标签: c# wpf mvvm

如何创建遵循MVVM模式的菜单栏 以及如何将视图模型绑定到xaml

我为单个项目和菜单列表视图模型创建了项目视图模型, 收集单个项目

ItemViewModel文件

/// <summary>
/// Menu item viewModel
/// </summary>
public class MenuItemViewModel : BaseViewModel
{
    #region Public Properties

    /// <summary>
    /// The displayed name
    /// </summary>
    public string Header { get; set; }

    /// <summary>
    /// The item order
    /// </summary>
    public int Order { get; set; }

    /// <summary>
    /// True if this item is Enabled
    /// </summary>
    public bool IsEnabled { get; set; }

    /// <summary>
    /// True if this item is currently selected
    /// </summary>        
    public bool IsSelected { get; set; }

    /// <summary>
    /// The item icon
    /// </summary>        
    public string Icon { get; set; }

    /// <summary>
    /// The parent view model.
    /// </summary>        
    public MenuListViewModel Parent { get; set; }

    #endregion

    #region Public Commands

    /// <summary>
    /// The command for when the item is clicked
    /// </summary>
    public ICommand OpenCommand { get; set; }


    #endregion

    #region Constructor
    /// <summary>
    /// Default constructor
    /// </summary>
    public MenuItemViewModel()
    {
        // Create commands
        OpenCommand = new RelayCommand(ItemCommand);
    } 
    #endregion

    #region Command Methods

    /// <summary>
    /// When the item is clicked 
    /// </summary>
    public virtual void ItemCommand() { }

    #endregion
}

MenuListViewModel文件

/// <summary>
/// Sub Menu item viewModel
/// </summary>
public class MenuListViewModel : BaseViewModel
{

    #region Protected Members

    /// <summary>
    /// The items list
    /// </summary>
    protected ObservableCollection<MenuItemViewModel> mItemsChildren;

    /// <summary>
    /// The items list
    /// </summary>
    protected ObservableCollection<Action> mChildrenCommands;

    /// <summary>
    /// The subMenu list
    /// </summary>
    protected ObservableCollection<MenuListViewModel> mSubMentChildren;

    #endregion

    #region Public Properties

    /// <summary>
    /// The displayed name
    /// </summary>
    public string Header { get; set; }

    /// <summary>
    /// True if this item is Enabled
    /// </summary>

    public bool IsEnabled { get; set; }

    /// <summary>
    /// True if this item is currently selected
    /// </summary>        
    public bool IsSelected { get; set; }

    /// <summary>
    /// The item icon
    /// </summary>        
    public object Icon { get; set; }

    /// <summary>
    /// The menu order
    /// </summary>
    public int Order { get; set; }

    /// <summary>
    /// The parent view model.
    /// </summary>
    public MenuListViewModel ParentViewModel { get; set; }

    /// <summary>
    /// The items list
    /// </summary>
    public ObservableCollection<MenuItemViewModel> Items
    {
        get => mItemsChildren;
        set
        {
            // Make sure list has changed
            if (mItemsChildren == value)
                return;

            // Update value
            mItemsChildren = value;
        }
    }

    /// <summary>
    /// The items list
    /// </summary>
    public ObservableCollection<Action> ItemsCommands
    {
        get => mChildrenCommands;
        set
        {
            // Make sure list has changed
            if (mChildrenCommands == value)
                return;

            // Update value
            mChildrenCommands = value;
        }
    }

    /// <summary>
    /// The subMenu items for the list
    /// </summary>
    public ObservableCollection<MenuListViewModel> SubMenuItems
    {
        get => mSubMentChildren;
        set
        {
            // Make sure list has changed
            if (mSubMentChildren == value)
                return;

            // Update value
            mSubMentChildren = value;
        }
    }

    #endregion

    public virtual void LoadChildMenuItems()
    {

    }
}

Xaml文件

<UserControl.Resources>
    <Style TargetType="{x:Type MenuItem}">
        <Setter Property="Header" Value="{Binding Path=Header}"/>
        <Setter Property="Command" Value="{Binding Path=Command}"/>
    </Style>
    <HierarchicalDataTemplate 
    DataType="{x:Type local:MenuBarViewModel}"
    ItemsSource="{Binding Path=Items}">
    </HierarchicalDataTemplate>
</UserControl.Resources>

<Menu DockPanel.Dock="Top" ItemsSource="{Binding Path=Items}"/>

那么如何在xaml文件中添加此viewModles并将其绑定到Headers和命令

1 个答案:

答案 0 :(得分:0)

您的MenuItemViewModel中没有集合Items。 hierarchicaldatatemplate的工作方式是将子菜单的itemssource绑定到父菜单的属性。既然您没有,那最好的事情就是获得最高水平。

下面是一些简化的标记和代码:

    <Menu ItemsSource="{Binding MenuItems}" Height="30">
        <Menu.Resources>
            <Style TargetType="{x:Type MenuItem}">
                <Setter Property="Header" Value="{Binding Path=Header}"/>
                <Setter Property="Command" Value="{Binding Path=Command}"/>
            </Style>
            <HierarchicalDataTemplate 
                 DataType="{x:Type local:MenuItemVM}"
                 ItemsSource="{Binding SubItems}">
            </HierarchicalDataTemplate>
        </Menu.Resources>
    </Menu>

在我的窗口viewmodel中,我设置了一些基本数据:

    private ObservableCollection<MenuItemVM> menuItems = new ObservableCollection<MenuItemVM>(
        new List<MenuItemVM>
        {
            new MenuItemVM{ Header="File", SubItems= new ObservableCollection<MenuItemVM>( new List<MenuItemVM>
            {
                new MenuItemVM{ Header="Open"},
                new MenuItemVM{ Header="Save"}
            })
            }
        }

        );

还有我简化的menuitemvm:

public class MenuItemVM
{
    public string Header { get; set; }
    public ICommand Command { get; set; }
    public ObservableCollection<MenuItemVM> SubItems { get; set; }
}