Как в WPF правильно создавать Меню придерживаясь паттерна MVVM?
В MainView.xaml
<Window.DataContext>
<vm:MainViewModel/>
</Window.DataContext>
<Grid>
<Menu Height="22" VerticalAlignment="Top">
<MenuItem Header="Файл">
<MenuItem Header="Выход"></MenuItem>
</MenuItem>
<MenuItem Header="Правка" >
<MenuItem Header="Очистить "></MenuItem>
</MenuItem>
<MenuItem Header="Данные" RenderTransformOrigin="0.649,1.833" >
<MenuItem Header="Пункт 1" Command="{Binding ReferenceDataClickCommand}" ToolTip="Получить справочные данные"/>
<MenuItem Header="Пункт 2" ToolTip="Получить справочные данные"></MenuItem>
<MenuItem Header="Пункт 3" ToolTip="Получить справочные данные"></MenuItem>
</MenuItem>
<MenuItem Header="Справка" ></MenuItem>
</Menu>
</Grid>
Нужно для каждого пункта делать свой Binding?
<MenuItem Header="Данные" RenderTransformOrigin="0.649,1.833" >
<MenuItem Header="Пункт 1" Command="{Binding FirstMenuItemClickCommand}" ToolTip="Получить справочные данные"/>
<MenuItem Header="Пункт 2" Command="{Binding SecondMenuItemClickCommand}" ToolTip="Получить справочные данные"></MenuItem>
<MenuItem Header="Пункт 3" Command="{Binding ThirdMenuItemClickCommand}" ToolTip="Получить справочные данные"></MenuItem>
</MenuItem>
Или можно как-то универсально?
<MenuItem Header="Данные" RenderTransformOrigin="0.649,1.833" >
<MenuItem Header="Пункт 1" Command="{Binding MenuItemClickCommand}" ToolTip="Получить справочные данные"/>
<MenuItem Header="Пункт 2" Command="{Binding MenuItemClickCommand}" ToolTip="Получить справочные данные"></MenuItem>
<MenuItem Header="Пункт 3" Command="{Binding MenuItemClickCommand}" ToolTip="Получить справочные данные"></MenuItem>
</MenuItem>
и далее из MainViewModel.cs как-то получить значение Header?
Ключевой вопрос "как правильно". То, что выше - мои предположения и наблюдения.
Ответы (1 шт):
Ну зависит от твоих целей - в целом нет ничего зазорного, чтобы ручками в xaml запилить, если меню статичное. Можно на каждый пункт свою команду вешать, а можно одну команду сделать и передавать параметром (CommandParameter) ид кнопки - и там уже обрабатывать - хотя спорный вариант, не берусь рекомендовать так делать, разве что для некоторых однотипных команд... хм..
Можно через биндинги динамически меню сделать. Вот так:
public class MainViewModel : ViewModelBase
{
public List<MenuItemViewModel> Menu { get; set; }
public string Title => "MenuExample";
/// <summary>
/// Initializes a new instance of the MainViewModel class.
/// </summary>
public MainViewModel()
{
var fileMenu = new List<MenuItemViewModel>
{
new MenuItemViewModel("Сохранить", new RelayCommand(() => { System.Windows.Forms.MessageBox.Show("Saved");}))
};
Menu = new List<MenuItemViewModel>
{
new MenuItemViewModel("Файл", null, fileMenu),
new MenuItemViewModel("Выход", new RelayCommand(()=> {System.Environment.Exit(0);}))
};
}
}
public class MenuItemViewModel : ViewModelBase
{
public string Title { get; set; }
public RelayCommand Command { get; set; }
public List<MenuItemViewModel> Submenu { get; set; }
public MenuItemViewModel ()
{
Submenu = new List<MenuItemViewModel> ();
}
public MenuItemViewModel (string title, RelayCommand command, List<MenuItemViewModel> submenu = null) {
Title = title;
Command = command;
Submenu = submenu ?? new List<MenuItemViewModel> ();
}
}
в xaml:
<Menu ItemsSource="{Binding Menu}">
<Menu.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="Command" Value="{Binding Command}" />
<Setter Property="CommandParameter"></Setter>
</Style>
</Menu.ItemContainerStyle>
<Menu.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type viewModel:MenuItem}" ItemsSource="{Binding Path=Submenu}">
<TextBlock Text="{Binding Title}"/>
</HierarchicalDataTemplate>
</Menu.ItemTemplate>
</Menu>
Учтите тут все в лоб и грубо сделано - просто концепт =)