UWP CommandBar溢出按钮问题:弹出层冲突与圆角不生效求助
我来帮你搞定这两个UWP CommandBar的问题,这俩坑我之前也踩过,给你梳理下具体的解决办法:
这个问题我太熟悉了——当带Flyout的AppBarButton被挤到MoreButton的溢出菜单里时,点击它会先触发MoreButton的Flyout关闭,同时自己的Flyout刚弹出来就被关掉,体验特别差。把它转成MenuFlyoutSubItem确实是最优解,具体实现可以这么做:
实现步骤:
- 首先给你的CommandBar起个名字(比如
x:Name="MainCommandBar"),方便后台代码操作 - 监听CommandBar的
OverflowButtonOpening事件,在溢出菜单打开前,把目标AppBarButton替换成MenuFlyoutSubItem:
MainCommandBar.OverflowButtonOpening += (sender, e) => { // 找到你要转换的那个AppBarButton(替换成你的按钮Name) var targetButton = MainCommandBar.PrimaryCommands.OfType<AppBarButton>() .FirstOrDefault(b => b.Name == "YourTargetFlyoutButton"); if (targetButton != null && targetButton.IsInOverflow) { // 先从原命令集合里移除按钮 MainCommandBar.PrimaryCommands.Remove(targetButton); // 创建对应的MenuFlyoutSubItem var subItem = new MenuFlyoutSubItem { Text = targetButton.Label, Icon = targetButton.Icon }; // 把原按钮Flyout里的所有菜单项复制过来 if (targetButton.Flyout is MenuFlyout originalFlyout) { foreach (var item in originalFlyout.Items.ToList()) { originalFlyout.Items.Remove(item); subItem.Items.Add(item); } } // 添加到溢出菜单的命令集合里 MainCommandBar.SecondaryCommands.Add(subItem); } };
- 别忘了监听
OverflowButtonClosing事件,在溢出菜单关闭后把SubItem转回去,避免下次打开时重复添加:
MainCommandBar.OverflowButtonClosing += (sender, e) => { var targetSubItem = MainCommandBar.SecondaryCommands.OfType<MenuFlyoutSubItem>() .FirstOrDefault(s => s.Text == "你的按钮标签"); if (targetSubItem != null) { // 重新创建AppBarButton var newButton = new AppBarButton { Label = targetSubItem.Text, Icon = targetSubItem.Icon, Flyout = new MenuFlyout() }; // 把SubItem的菜单项复制回去 foreach (var item in targetSubItem.Items.ToList()) { targetSubItem.Items.Remove(item); (newButton.Flyout as MenuFlyout).Items.Add(item); } // 替换回原命令集合 MainCommandBar.SecondaryCommands.Remove(targetSubItem); MainCommandBar.PrimaryCommands.Add(newButton); } };
这样处理后,当按钮被折叠到溢出菜单时,就会变成一个可展开的子菜单,点击它只会展开自己的选项,不会和MoreButton的Flyout冲突了。
你设置了CornerRadius="20"却还是矩形,核心问题是你引用的StaticResource EllipsisButton样式覆盖了CornerRadius的绑定。UWP的控件样式优先级很高,如果自定义样式里的Border元素没有绑定到Button的CornerRadius属性,你直接在Button上设置的属性就不会生效。
解决办法:
修改现有EllipsisButton样式:
找到你定义EllipsisButton样式的地方,找到里面的根Border(一般叫RootBorder),把它的CornerRadius改成绑定到模板父级:<Border x:Name="RootBorder" CornerRadius="{TemplateBinding CornerRadius}" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> <!-- 样式里的其他内容 --> </Border>这样你在Button上设置的
CornerRadius="20"就会被模板里的Border继承。临时覆盖模板(不用改原样式):
如果不想修改全局的EllipsisButton样式,可以直接在MoreButton里重写模板:<Button x:Name="MoreButton" Grid.Column="1" MinHeight="{ThemeResource AppBarThemeCompactHeight}" Padding="{ThemeResource CommandBarMoreButtonMargin}" VerticalAlignment="Top" Control.IsTemplateKeyTipTarget="True" CornerRadius="20" Foreground="{TemplateBinding Foreground}" IsAccessKeyScope="True" Visibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=CommandBarTemplateSettings.EffectiveOverflowButtonVisibility}"> <Button.Template> <ControlTemplate TargetType="Button"> <Border CornerRadius="{TemplateBinding CornerRadius}" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" /> </Border> </ControlTemplate> </Button.Template> <FontIcon x:Name="EllipsisIcon" Height="{ThemeResource AppBarExpandButtonCircleDiameter}" VerticalAlignment="Center" FontFamily="{ThemeResource SymbolThemeFontFamily}" FontSize="20" Glyph="" /> </Button>这样就能强制让MoreButton的Border使用你设置的圆角值了。
内容的提问来源于stack exchange,提问作者Seaky Lone

