【问题标题】:Microsoft PRISM: Using multiple regions in a WPF Menu controlMicrosoft PRISM:在 WPF 菜单控件中使用多个区域
【发布时间】:2023-03-25 16:54:01
【问题描述】:

我们正在 PRISM 和大量模块的帮助下实施模块化软件。该框架包含 MainWindow Shell,其中定义了工具栏和菜单。每个模块都应该能够在运行时添加自己的工具栏和菜单条目,例如初始化。为此,使用了区域管理器。对于工具栏,它运行良好,但对于菜单,出现了一些问题:

<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>

.....

区域RegionNames.MainMenu 用于常见条目,如文件、编辑、视图。区域RegionNames.AppMenu 是为几个模块添加自己的菜单。区域RegionNames.HelpMenu 用于常用条目窗口和帮助。使用区域的动机是为了获得菜单条目的顺序。每个模块以这种方式为菜单创建自己的视图(用户控件)和视图模型:

<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 区域)会获得菜单条目。同样的行为出现在两个不同的视图中。似乎最后一个覆盖了第一个。

我搜索了合适的解决方案,但不幸的是直到现在我还没有找到适合这个用例的解决方案。希望我能以这种方式找到解决此问题的解决方案或另一种方法。提前致谢。

【问题讨论】:

    标签: c# wpf menu prism


    【解决方案1】:
    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.HelpMenu

    2) 区域名称。应用菜单

    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)
    

    【讨论】:

      【解决方案2】:

      感谢您的回答。但我是按照你描述的方式来做的

          IRegionViewRegistry regionViewRegistry = ServiceLocator.Current.GetInstance<IRegionViewRegistry>();
          regionViewRegistry.RegisterViewWithRegion(RegionNames.MainMenu, typeof(MainMenu));
          regionViewRegistry.RegisterViewWithRegion(RegionNames.HelpMenu, typeof(HelpMenu));
      

      例如菜单项的用户控件

      <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 不是顶级而不是二级,并且无法将帮助菜单注入帮助菜单区域。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-12-03
        • 2016-07-29
        • 2023-04-03
        • 1970-01-01
        • 2013-10-31
        • 2010-12-04
        • 1970-01-01
        相关资源
        最近更新 更多