与ViewModel绑定的MVVM动态菜单UI

我正在与一个关于LoB应用程序的团队合作。 我们希望有一个动态Menu控件,它根据登录的用户配置文件创建菜单。 在以前的开发方案(即ASP.NET)中,我们使用迭代描述集合的数据并动态生成MenuItem 。 在MVVM中我该怎么做? 我可以将XAML视图与描述菜单元素的ViewModel分开吗?

解:

通过评论员的输入,我能够使用ViewModel中的数据动态绑定Menu 。 这篇文章也很有帮助。

XAML:

    [...]      

Menu数据类:

 public class Menu : ViewModelBase { public Menu() { IsEnabled = true; Children = new List(); } #region [ Menu Properties ] private bool _isEnabled; private string _menuText; private ICommand _command; private IList _children; public string MenuText { get { return _menuText; } set { _menuText = value; base.OnPropertyChanged("MenuText"); } } public bool IsEnabled { get { return _isEnabled; } set { _isEnabled = value; base.OnPropertyChanged("IsEnabled"); } } public ICommand Command { get { return _command; } set { _command = value; base.OnPropertyChanged("Command"); } } public IList Children { get { return _children; } set { _children = value; } } #endregion } 

尝试这样的事情:

 public class MenuItemViewModel { public MenuItemViewModel() { this.MenuItems = new List(); } public string Text { get; set; } public IList MenuItems { get; private set; } } 

假设您的DataContext有一个名为MenuItems的属性,它是MenuItemViewModel的列表。 这样的事情应该有用,然后:

            

这应该可以让你到达目的地

        

请注意,在我的示例中,我的菜单Item具有类型为ICommand的属性,称为Command。

此解决方案不需要代码中的任何代码,这使得它更简单的解决方案。

                    

MenuItem表示为:

 public class MenuItemViewModel : BaseViewModel { ///  /// Initializes a new instance of the  class. ///  /// The parent view model. public MenuItemViewModel(MenuItemViewModel parentViewModel) { ParentViewModel = parentViewModel; _childMenuItems = new ObservableCollection(); } private ObservableCollection _childMenuItems; ///  /// Gets the child menu items. ///  /// The child menu items. public ObservableCollection ChildMenuItems { get { return _childMenuItems; } } private string _header; ///  /// Gets or sets the header. ///  /// The header. public string Header { get { return _header; } set { _header = value; NotifyOnPropertyChanged("Header"); } } ///  /// Gets or sets the parent view model. ///  /// The parent view model. public MenuItemViewModel ParentViewModel { get; set; } public virtual void LoadChildMenuItems() { } } 

具体的MenuItem可以直接实例化,也可以通过inheritance创建自己的SubType。

我知道这是一个旧post,但我需要这个以及如何绑定命令。

至于Guge关于如何绑定命令的问题:VMMenuItems是我的视图模型类中的属性

 ObservableCollection 

和Menu是上面定义的类。 MenuItem的Command属性绑定到Menu类的Command属性。 在我的视图模型类中

 Menu.Command = _fou 

哪里

 private ICommand _fou; 

xaml

        

如果你想知道如何做分隔符,那真的很容易。

下面的代码是我的ViewModel的一部分。 由于XAML使用reflection,我需要做的就是返回’object’,它可以是MenuItemViewModelSeparator ,或者(如果出于某些我需要的原因)实际的MenuItem

我正在使用yield来动态生成项目,因为它似乎对我来说更好。 即使我正在使用yield – 如果项目发生了变化,我仍然需要像往常一样为"ContextMenu"引发一个PropertyChanged事件,但是在需要之前我不会不必要地生成列表。

  public IEnumerable ContextMenu { get { // ToArray() needed or else they get garbage collected return GetContextMenu().ToArray(); } } public IEnumerable GetContextMenu() { yield return new MenuItemViewModel() { Text = "Clear all flags", }; // adds a normal 'Separator' menuitem yield return new Separator(); yield return new MenuItemViewModel() { Text = "High Priority" }; yield return new MenuItemViewModel() { Text = "Medium Priority" }; yield return new MenuItemViewModel() { Text = "Low Priority" }; yield break; }