Microsoft PRISM:在WPF菜单控件中使用多个区域
本文关键字:区域 控件 PRISM WPF 菜单 Microsoft | 更新日期: 2023-09-27 18:07:33
我们正在PRISM和大量模块的帮助下实现模块化软件。该框架包含MainWindowShell,其中定义了工具栏和菜单。当模块初始化时,每个模块都应该能够在运行时添加自己的工具栏和菜单项。为此,使用区域经理。对于工具栏,它工作得很好,但对于菜单,很少出现问题:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<!--
<Menu Grid.Row="0" IsMainMenu="True">
<MenuItem Header="Test" />
</Menu>
-->
<!-- Main Menu -->
<StackPanel Grid.Row="0" Orientation="Horizontal">
<ItemsControl Name="MainMenuRegion" prism:RegionManager.RegionName="{x:Static common:RegionNames.MainMenu}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
<ItemsControl Name="AppMenuRegion" prism:RegionManager.RegionName="{x:Static common:RegionNames.AppMenu}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
<ItemsControl Name="HelpMenuRegion" prism:RegionManager.RegionName="{x:Static common:RegionNames.HelpMenu}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</StackPanel>
Region RegionNames.MainMenu
用于常见条目,如File、Edit、Veiw。区域RegionNames.AppMenu
用于多个模块添加自己的菜单。Region RegionNames.HelpMenu
用于常见条目Window和Help。使用区域的动机是获得菜单项的订单。每个模块都以这种方式为菜单创建自己的视图(用户控制(和视图模型:
<Menu ItemsSource="{Binding MainMenuItems}" />
此外,对于菜单项,我们使用了一个数据模板:
<Style TargetType="{x:Type MenuItem}">
<Setter Property="Command" Value="{Binding Command}" />
<Setter Property="CommandParameter" Value="{Binding CommandParameter}" />
<Setter Property="Header" Value="{Binding Text, UpdateSourceTrigger=PropertyChanged}" />
<Setter Property="IsChecked" Value="{Binding IsChecked, UpdateSourceTrigger=PropertyChanged}" />
<Setter Property="IsEnabled" Value="{Binding IsEnabled, UpdateSourceTrigger=PropertyChanged}" />
<Setter Property="Visibility" Value="{Binding IsVisible, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource VisibilityConverter}}" />
<Setter Property="ItemsSource" Value="{Binding Children, UpdateSourceTrigger=PropertyChanged}" />
<Setter Property="Icon" Value="{DynamicResource itemIcon}" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsSeparator, UpdateSourceTrigger=PropertyChanged}" Value="true">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Separator />
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Icon}" Value="{x:Null}">
<Setter Property="Icon" Value="{x:Null}" />
</DataTrigger>
</Style.Triggers>
</Style>
但这种方法行不通。当试图在两个不同的区域注册相同的视图时,如下所示:
IRegionViewRegistry regionViewRegistry = ServiceLocator.Current.GetInstance<IRegionViewRegistry>();
regionViewRegistry.RegisterViewWithRegion(RegionNames.HelpMenu, typeof(MainMenu));
regionViewRegistry.RegisterViewWithRegion(RegionNames.MainMenu, typeof(MainMenu));
只有最后一个区域(MainMenu区域(将获得菜单条目。相同的行为是在两种不同观点的情况下发生的。似乎最后一个覆盖了第一个。
我搜索了合适的解决方案,但不幸的是,到目前为止,我还没有找到适合这个用例的解决方案。希望我能以这种方式找到解决方案或其他方法来解决这个问题。提前谢谢。
IRegionViewRegistry regionViewRegistry = ServiceLocator.Current.GetInstance<IRegionViewRegistry>();
regionViewRegistry.RegisterViewWithRegion(RegionNames.HelpMenu, typeof(MainMenu)); // registering same view with diferent region
regionViewRegistry.RegisterViewWithRegion(RegionNames.MainMenu, typeof(MainMenu));
如果我理解正确,那么你定义了3个区域(在你的情况下,可以添加自定义用户控件的占位符是菜单项。(
1( RegionNames.Help菜单
2( RegionNames。应用程序菜单
3( RegionNames.MainMenu
现在,您需要创建3个自定义用户控件,并将它们注册到区域中。
public partial class MainMenuSelection : UserControl
{
public MainMenuSelection ()
{
InitializeComponent();
}
}
类似的应用程序菜单和帮助菜单分别
然后你可以像一样使用
ServiceLocator.Current.GetInstance<IRegionViewRegistry>();
regionViewRegistry.RegisterViewWithRegion(RegionNames.HelpMenu,typeof(HelpMenuSelection));
regionViewRegistry.RegisterViewWithRegion(RegionNames.MainMenu, typeof(MainMenuSelection)); // You are registering view (mainmenuselection) with unique region placeholder(RegionNames.MainMenu)
感谢您的回答。但我是这样做的,你描述
IRegionViewRegistry regionViewRegistry = ServiceLocator.Current.GetInstance<IRegionViewRegistry>();
regionViewRegistry.RegisterViewWithRegion(RegionNames.MainMenu, typeof(MainMenu));
regionViewRegistry.RegisterViewWithRegion(RegionNames.HelpMenu, typeof(HelpMenu));
以及例如菜单项的UserControl
<UserControl x:Class="XXX.GUI.View.MainMenu"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignHeight="300"
d:DesignWidth="300"
mc:Ignorable="d">
<MenuItem ItemsSource="{Binding MainMenuItems}" />
</UserControl>
在我的ViewModel中,创建了MainMenuItems的可观察集合。当我以这种方式这样做时,MenuItem不是顶级的,而是第二级的,并且不可能将帮助菜单插入到帮助菜单区域中。