带有多个溢出菜单的 UWP CommandBar,例如 Word Mobile?

UWP CommandBar with multiple overflow menus like Word Mobile?

我的桌面上有一个基本的 C# UWP 应用程序 运行。该应用程序的布局类似于 Word Mobile,即它有一个主菜单,下面有一个命令栏以应用各种命令。

默认的 CommandBar 有主要命令(显示为图标)和显示在溢出菜单中的次要命令。

Word Mobile 应用程序使用带有 "groups" 个命令按钮的特殊命令栏。如果 window 尺寸太小而无法显示所有命令,每个组都有自己的溢出菜单(请参见下面的屏幕截图)。

有没有办法使用标准 XAML 控件来获得这些 "grouped" 命令及其自己的溢出菜单?如果没有,实现这样的自定义控件的策略是什么?

示例:

(1) 宽 window:CommandBar 显示所有命令按钮:

(2) 小 window:两个独立的溢出菜单按钮:

它可能不是特别复杂,但仍然需要大量工作。它可能源自功能区,其中有多个组具有项目折叠和丢弃优先级(我认为)并且项目按优先顺序丢弃。

您需要有一个容器面板来读取其中包含的组和 MeasureOverride 中的优先级 - 它会在 space 压力发生时驱动组中的折叠项。

ToolStrip control in my toolkit has code to move items between the toolstrip and the overflow dropdown (check sample here),这可能是实现对带状折叠的支持的良好开端。

IIRC CommandBar 的官方示例也实现了在 PrimaryCommandsSecondaryCommands 之间移动项目的逻辑,您可以研究一下。

抱歉延迟,但我想我会 post 概念验证答案。 对于此示例,我在 CommandBar 中创建了 7 操作 AppBarButton,包括以下内容

2 独立的按钮 - AllAppsButtonCalculatorButton

2 属于 CameraGroup 的按钮 - CameraButtonAttachCameraButton

3 属于字体组的按钮 - BoldButtonFontButton斜体按钮

我的想法是,如果屏幕尺寸小于 501 像素,我会使用 VisualStateManagerAdaptiveTriggers 来显示 Group V 形按钮而不是动作按钮。然后通过单击打开相关 Popup 控件的向下 V 形显示操作按钮。 如果屏幕增加到 501 像素或以上,使用 AdaptiveTriggers 再次隐藏弹出窗口。

MainPage.xaml

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="CameraGroupStates">
            <VisualState x:Name="Default">
                <VisualState.StateTriggers>
                    <AdaptiveTrigger MinWindowWidth="501" />
                </VisualState.StateTriggers>
                <VisualState.Setters>
                    <Setter Target="CameraButton.Visibility" Value="Visible"/>
                    <Setter Target="AttachCameraButton.Visibility" Value="Visible" />
                    <Setter Target="CameraGroupButton.Visibility" Value="Collapsed" />
                    <Setter Target="CameraGroupPopup.IsOpen" Value="false" />

                    <Setter Target="FontButton.Visibility" Value="Visible"/>
                    <Setter Target="BoldButton.Visibility" Value="Visible" />
                    <Setter Target="ItalicButton.Visibility" Value="Visible" />
                    <Setter Target="FontGroupButton.Visibility" Value="Collapsed" />
                    <Setter Target="FontGroupPopup.IsOpen" Value="false" />
                </VisualState.Setters>
            </VisualState>
            <VisualState x:Name="Minimal">
                <VisualState.StateTriggers>
                    <AdaptiveTrigger MinWindowWidth="0" />
                </VisualState.StateTriggers>
                <VisualState.Setters>
                    <Setter Target="CameraButton.Visibility" Value="Collapsed"/>
                    <Setter Target="AttachCameraButton.Visibility" Value="Collapsed" />
                    <Setter Target="CameraGroupButton.Visibility" Value="Visible" />

                    <Setter Target="FontButton.Visibility" Value="Collapsed"/>
                    <Setter Target="BoldButton.Visibility" Value="Collapsed" />
                    <Setter Target="ItalicButton.Visibility" Value="Collapsed" />
                    <Setter Target="FontGroupButton.Visibility" Value="Visible" />
                </VisualState.Setters>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
    <CommandBar x:Name="MainCommandBar" Height="50">            
        <AppBarButton x:Name="AllAppsButton" Icon="AllApps"></AppBarButton>            
        <AppBarButton x:Name="CameraButton" Icon="Camera"></AppBarButton>
        <AppBarButton x:Name="AttachCameraButton" Icon="AttachCamera"></AppBarButton>

        <!--This is the Group Chevron button for Camera-->
        <AppBarButton x:Name="CameraGroupButton" Visibility="Collapsed" Content="&#xE019;"
                      Click="CameraGroupButton_Click">
            <AppBarButton.ContentTemplate>
                <DataTemplate>
                    <Grid>
                        <TextBlock Text="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Content}"
                                   FontFamily="Segoe MDL2 Assets" HorizontalAlignment="Center"></TextBlock>
                    </Grid>
                </DataTemplate>
            </AppBarButton.ContentTemplate>
        </AppBarButton>
        <AppBarButton x:Name="CaluclatorButton" Icon="Calculator"></AppBarButton>
        <AppBarButton x:Name="BoldButton" Icon="Bold"></AppBarButton>
        <AppBarButton x:Name="FontButton" Icon="Font"></AppBarButton>
        <AppBarButton x:Name="ItalicButton" Icon="Italic"></AppBarButton>

        <!--This is the Group Chevron button for Fonts-->
        <AppBarButton x:Name="FontGroupButton" Visibility="Collapsed" Content="&#xE019;"
                      Click="FontGroupButton_Click">
            <AppBarButton.ContentTemplate>
                <DataTemplate>
                    <Grid>
                        <TextBlock Text="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Content}"
                                   FontFamily="Segoe MDL2 Assets" HorizontalAlignment="Center"></TextBlock>
                    </Grid>
                </DataTemplate>
            </AppBarButton.ContentTemplate>
        </AppBarButton>
    </CommandBar>
    <Popup x:Name="CameraGroupPopup" HorizontalAlignment="Right" HorizontalOffset="-120"
           VerticalOffset="50" IsOpen="False">
        <StackPanel Orientation="Horizontal" Width="120" Height="60" Background="LightGray"
                    HorizontalAlignment="Center">
            <AppBarButton x:Name="CameraGroupCameraButton" Icon="Camera" Width="50" Height="50"
                          Foreground="Black"/>
            <AppBarButton x:Name="CameraGroupAttachCameraButton" Icon="AttachCamera"
                          Foreground="Black" Width="50" Height="50"></AppBarButton>
        </StackPanel>
    </Popup>
    <Popup x:Name="FontGroupPopup" HorizontalAlignment="Right" HorizontalOffset="-170"
           VerticalOffset="50" IsOpen="False">
        <StackPanel Orientation="Horizontal" Width="170" Height="60" Background="LightGray"
                    HorizontalAlignment="Center">
            <AppBarButton x:Name="FontGroupBoldButton" Icon="Bold" Width="50" Height="50"
                          Foreground="Black"/>
            <AppBarButton x:Name="FontGroupFontButton" Icon="Font"
                          Foreground="Black" Width="50" Height="50"></AppBarButton>
            <AppBarButton x:Name="FontGroupItalicButton" Icon="Italic"
                          Foreground="Black" Width="50" Height="50"></AppBarButton>
        </StackPanel>
    </Popup>
</Grid>

后面的代码包含用于 hide/show 相关弹出窗口的 2 个字段和 2 个事件,将人字形更改为 up/down 箭头。

public sealed partial class MainPage : Page
{
    public bool CameraGroupIsOpen { get; set; } = false;
    public bool FontGroupIsOpen { get; set; } = false;

    public MainPage()
    {
        this.InitializeComponent();
    }

    private void CameraGroupButton_Click(object sender, RoutedEventArgs e)
    {
        if (CameraGroupIsOpen)
        {
            CameraGroupPopup.IsOpen = false;
            CameraGroupButton.Content = "\uE019";
            CameraGroupIsOpen = false;
        }
        else
        {
            CameraGroupPopup.IsOpen = true;
            CameraGroupButton.Content = "\uE018";
            CameraGroupIsOpen = true;
        }
    }

    private void FontGroupButton_Click(object sender, RoutedEventArgs e)
    {
        if (FontGroupIsOpen)
        {
            FontGroupPopup.IsOpen = false;
            FontGroupButton.Content = "\uE019";
            FontGroupIsOpen = false;
        }
        else
        {
            FontGroupPopup.IsOpen = true;
            FontGroupButton.Content = "\uE018";
            FontGroupIsOpen = true;
        }
    }
}

相当多的代码无疑可以作为 CustomControl 得到极大改进,但想展示这个想法。希望对你有帮助