C# 根据WPF中的情况自定义菜单

C# 根据WPF中的情况自定义菜单,c#,wpf,xaml,mvvm,binding,C#,Wpf,Xaml,Mvvm,Binding,如何根据WPF中的情况自定义菜单? 我有一个带有基本菜单的主窗口。在这个窗口中,我可以加载不同的用户控件,然后我希望根据使用的用户控件使用不同的菜单选项来扩展菜单 例如: Main menu: File Open - MRU - Exit For viewing of UserControl 1: File Open Edit - MRU - Exit For viewing of UserControl 2: File

如何根据WPF中的情况自定义菜单? 我有一个带有基本菜单的主窗口。在这个窗口中,我可以加载不同的用户控件,然后我希望根据使用的用户控件使用不同的菜单选项来扩展菜单

例如:

Main menu:
File
   Open
   -
   MRU
   -
   Exit


For viewing of UserControl 1:
File
   Open
   Edit
   -
   MRU
   -
   Exit

For viewing of UserControl 2:
File
   Open
   Edit
   -
   MRU
   -
   Exit
View
   Show codes
   Show capital letters

In Editing
File
   Open
   Save
   Save as...
   -
   MRU
   -
   Exit
Edit
   Add
   Remove
   Move
   -
   Cancle Edit

我会将菜单绑定到一个集合,并让不同的UserControls在加载时更改集合

编辑-下面是一个示例

您的主视图将包含以下内容

<Menu ItemsSource="{Binding Path=CurrentUserControl.MenuItems}">
    <Menu.Resources>
        <Style TargetType="{x:Type MenuItem}">
            <Setter Property="Header" Value="{Binding MenuItemText}" />
            <Setter Property="Command" Value="{Binding MenuItemCommand}" />
            <Setter Property="CommandParameter" Value="{Binding MenuItemCommandParameter}" />
        </Style>
    </Menu.Resources>
</Menu>

公共可观察收集菜单项;

我会将菜单绑定到一个集合,并让不同的用户控件在加载时更改集合

编辑-下面是一个示例

您的主视图将包含以下内容

<Menu ItemsSource="{Binding Path=CurrentUserControl.MenuItems}">
    <Menu.Resources>
        <Style TargetType="{x:Type MenuItem}">
            <Setter Property="Header" Value="{Binding MenuItemText}" />
            <Setter Property="Command" Value="{Binding MenuItemCommand}" />
            <Setter Property="CommandParameter" Value="{Binding MenuItemCommandParameter}" />
        </Style>
    </Menu.Resources>
</Menu>

公共可观察收集菜单项;
我确实找到了一个解决方案: 但是应该有更好的办法

我确实找到了解决办法:
但是应该有更好的方法

如何将某些菜单选项的可见性绑定到ViewModel中的布尔值,并使用IValueConverter在可见和折叠之间切换?

如何将某些菜单选项的可见性绑定到ViewModel中的布尔值,使用IValueConverter在可见和折叠之间切换?

您可以使用CompositeCollection将多个集合合并为一个集合。 以下示例来自:


您可以使用CompositeCollection将多个集合合并为一个集合。 以下示例来自:



一个简单的方法是在代码隐藏中构建一系列if-then构造,根据用户控件可见的内容更改各种菜单项的可见性。

一个简单的方法是在代码隐藏中构建一系列if-then构造,更改各种菜单项的可见性,取决于哪些用户控件是可见的。

但是ui是从破坏MVVM的ViewModel创建的。菜单应该在相应用户控件的视图中,并且以任何方式与主程序中的菜单合并。您仍然可以在视图中创建菜单,但是,您可以将它们绑定到ViewModel中定义的ItemsSource,而不是在视图中手动构建菜单项。我不确定我是否真正理解您的意思。是的,我创建了视图的主菜单,但它的自定义是在视图模型中完成的。@magol我在回答中添加了一些示例代码。我没有时间做一个完整的模型,但我希望这将为您指明正确的方向。这个答案是一个非常好的方法,并且完全符合MVVM。视图模型是视图的抽象。填充菜单的组件应来自该视图的ViewModel。正如Rachel指出的,每个控件的ViewModel都有一组菜单选项,菜单控件可以绑定到这些选项。切换控件时,必须确保对“CurrentUserControl.MenuItems”调用OnPropertyChanged。但是,ui是从断开MVVM的ViewModel创建的。菜单应该在相应用户控件的视图中,并且以任何方式与主程序中的菜单合并。您仍然可以在视图中创建菜单,但是,您可以将它们绑定到ViewModel中定义的ItemsSource,而不是在视图中手动构建菜单项。我不确定我是否真正理解您的意思。是的,我创建了视图的主菜单,但它的自定义是在视图模型中完成的。@magol我在回答中添加了一些示例代码。我没有时间做一个完整的模型,但我希望这将为您指明正确的方向。这个答案是一个非常好的方法,并且完全符合MVVM。视图模型是视图的抽象。填充菜单的组件应来自该视图的ViewModel。正如Rachel指出的,每个控件的ViewModel都有一组菜单选项,菜单控件可以绑定到这些选项。切换控件时,必须确保对“CurrentUserControl.MenuItems”调用OnPropertyChanged,但所有菜单都在主窗口中编码。如果我想添加一个视图,那么我还必须更改主视图。最近我可能与IValueConverter合作太多了。。。也许您可以创建一个以菜单为参数的转换器,将菜单“转换”为参数和值之间的合并?然后,主窗口菜单绑定到usercontrol菜单,菜单资源作为转换器参数。缺点是您必须在参考资料中编辑主窗口菜单。它一点也不漂亮。但是所有的菜单都在主窗口中编码。如果我想添加一个视图,那么我还必须更改主视图。最近我可能与IValueConverter合作太多了。。。也许您可以创建一个以菜单为参数的转换器,将菜单“转换”为参数和值之间的合并?然后,主窗口菜单绑定到usercontrol菜单,菜单资源作为转换器参数。缺点是您必须在参考资料中编辑主窗口菜单。而且一点也不漂亮。
public ObservableCollection<MenuItem> MenuItems;
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:sys="clr-namespace:System;assembly=mscorlib">
  <Grid Background="Transparent">
    <Grid.Resources>
        <x:Array Type="{x:Type sys:Object}" x:Key="extensions">
            <Separator />
            <MenuItem Header="Extension MenuItem 1" />
            <MenuItem Header="Extension MenuItem 2" />
            <MenuItem Header="Extension MenuItem 3" />
        </x:Array>
    </Grid.Resources>
    <Grid.ContextMenu>
        <ContextMenu>
            <ContextMenu.ItemsSource>
                <CompositeCollection>
                    <MenuItem Header="Standard MenuItem 1" />
                    <MenuItem Header="Standard MenuItem 2" />
                    <MenuItem Header="Standard MenuItem 3" />
                    <CollectionContainer Collection="{StaticResource extensions}" />
                </CompositeCollection>
            </ContextMenu.ItemsSource>
        </ContextMenu>
    </Grid.ContextMenu>
  </Grid>
</Window>