MVVM Dynamic Menu UI from binding with ViewModel
c#, menu, mvvm, wpf
Solution
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>
Problem
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 } ```