带有多个溢出菜单的 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 的官方示例也实现了在 PrimaryCommands
和 SecondaryCommands
之间移动项目的逻辑,您可以研究一下。
抱歉延迟,但我想我会 post 概念验证答案。
对于此示例,我在 CommandBar
中创建了 7 操作 AppBarButton
,包括以下内容
2 独立的按钮 - AllAppsButton、CalculatorButton
2 属于 CameraGroup 的按钮 - CameraButton、AttachCameraButton
3 属于字体组的按钮 - BoldButton、FontButton、斜体按钮
我的想法是,如果屏幕尺寸小于 501 像素,我会使用 VisualStateManager
和 AdaptiveTriggers
来显示 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=""
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=""
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
得到极大改进,但想展示这个想法。希望对你有帮助
我的桌面上有一个基本的 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 的官方示例也实现了在 PrimaryCommands
和 SecondaryCommands
之间移动项目的逻辑,您可以研究一下。
抱歉延迟,但我想我会 post 概念验证答案。
对于此示例,我在 CommandBar
中创建了 7 操作 AppBarButton
,包括以下内容
2 独立的按钮 - AllAppsButton、CalculatorButton
2 属于 CameraGroup 的按钮 - CameraButton、AttachCameraButton
3 属于字体组的按钮 - BoldButton、FontButton、斜体按钮
我的想法是,如果屏幕尺寸小于 501 像素,我会使用 VisualStateManager
和 AdaptiveTriggers
来显示 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=""
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=""
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
得到极大改进,但想展示这个想法。希望对你有帮助