Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
654 views
in Technique[技术] by (71.8m points)

c# - MVVM Dynamic Menu UI from binding with ViewModel

I am working with a team on LoB application. We would like to have a dynamic Menu control, which creates the menu based on the logged in user profile. In previous development scenarios (namely ASP.NET) we use to iterate through data which describes collection and generate MenuItem dynamically. In MVVM how would I do this? Can I separate XAML view from ViewModel which describes menu elements?

Solution:

With inputs from commentators I were able to bind Menu dynamically with the data from ViewModel. This article was of great help too.

XAML:

<HierarchicalDataTemplate DataType="{x:Type self:Menu}" ItemsSource="{Binding Path=Children, UpdateSourceTrigger=PropertyChanged}">
    <ContentPresenter Content="{Binding Path=MenuText}" RecognizesAccessKey="True"/>
</HierarchicalDataTemplate>

[...]

<Menu Height="21" Margin="0" Name="mainMenu" VerticalAlignment="Top" HorizontalAlignment="Stretch" 
      ItemsSource="{Binding Path=MenuItems, UpdateSourceTrigger=PropertyChanged}" ItemContainerStyle="{StaticResource TopMenuItems}">
    <Menu.Background>
        <ImageBrush ImageSource="/Wpf.Modules;component/Images/MenuBg.jpg" />
    </Menu.Background>
</Menu>

Menu data class:

public class Menu : ViewModelBase
{
    public Menu()
    {
        IsEnabled = true;
        Children = new List<Menu>();
    }

    #region [ Menu Properties ]

    private bool _isEnabled;
    private string _menuText;
    private ICommand _command;
    private IList<Menu> _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<Menu> Children
    {
        get { return _children; }
        set
        {
            _children = value;
        }
    }

    #endregion
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Try something like this:

public class MenuItemViewModel
{
    public MenuItemViewModel()
    {
        this.MenuItems = new List<MenuItemViewModel>();
    }

    public string Text { get; set; }

    public IList<MenuItemViewModel> MenuItems { get; private set; }
}

Assume that your DataContext has a property called MenuItems which is a list of MenuItemViewModel. Something like this should work, then:

<Window x:Class="WpfApplication1.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:self="clr-namespace:WpfApplication1"
        Title="Window1" Height="300" Width="300">
    <Window.Resources>
        <HierarchicalDataTemplate DataType="{x:Type self:MenuItemViewModel}"
                                  ItemsSource="{Binding Path=MenuItems}">
            <ContentPresenter Content="{Binding Path=Text}" />
        </HierarchicalDataTemplate>
    </Window.Resources>
    <DockPanel>
        <Menu DockPanel.Dock="Top" ItemsSource="{Binding Path=MenuItems}" />
        <Grid />
    </DockPanel>
</Window>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...