В статье Using MVVM with Menus in WPF рассказывается о том, как реализовать контекстное меню в рамках паттерна MVVM. Идея такая — создается собственный класс для хранения параметров пункта меню:
public class MenuItem
{
public string Text { get; set; }
public List<MenuItem> Children { get; private set; }
public ICommand Command { get; set; }
public MenuItem(string item)
{
Text = item;
Children = new List<MenuItem>();
}
}
Используя этот класс, создается дерево данных меню для определенного элемента:
public List<MenuItem> MenuOptions
{
get {
var menu = new List<MenuItem>();
if (SupportedFileFormats.Count > 0)
{
var mi = new MenuItem("O_pen");
foreach(var fl in SupportedFileFormats)
{
var sff = fl;
mi.Children.Add(new MenuItem(fl.Attributes.Description)
{ Command = new DelegatingCommand(() => { LoadFromFormat(sff); })});
}
menu.Add(mi);
}
menu.Add(new MenuItem("Close _All") { Command = new DelegatingCommand(OnCloseAll, () => FileList.Count > 0)});
return menu;
}
}
На стороне xaml создается стиль, который связывает элемент управления пункта меню и наш собственный класс данных:
<Style x:Key="ContextMenuItemStyle">
<Setter Property="MenuItem.Header" Value="{Binding Text}"/>
<Setter Property="MenuItem.ItemsSource" Value="{Binding Children}"/>
<Setter Property="MenuItem.Command" Value="{Binding Command}" />
</Style>
Далее, стиль присваивается конкретному контролу и все работает:
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Image}" Width="16" Height="16" />
<TextBlock Margin="5" HorizontalAlignment="Left" VerticalAlignment="Center" Text="{Binding Header}" />
<StackPanel.ContextMenu>
<!-- Собственно меню -->
<ContextMenu ItemContainerStyle="{StaticResource ContextMenuItemStyle}" ItemsSource="{Binding MenuOptions}" />
</StackPanel.ContextMenu>
</StackPanel>