WPF上下文菜单自动宽度以适合内容
WPF Context Menu Auto Width to Fit Content
我正在开发一个 wpf .net core 5 应用程序。该应用程序支持多语言。此应用有 UserControl
和 ContextMenu
。
问题:
第一次打开上下文菜单时,它适合其内容的宽度,这是正常的。但是当更改应用程序语言并再次打开菜单时,它的宽度保持不变。这隐藏了它的内容!
备注:
如果应用程序以 语言 A 启动,然后语言更改为 语言 B.. 打开菜单时它适合 语言B内容反之
我认为这是 UI 引擎的一个错误。但是解决此问题的最佳方法是什么而不是手动设置菜单的宽度 OnContextMenuOpening
固定宽度根据当前语言?或者它如何在第一次渲染它的大小,以便我每次打开时都可以这样调用?
截图1
截图2
答案
经过数小时的搜索后,我无法找到无需手动设置宽度即可修复此错误的方法。即使是手动方式在设置子菜单项的宽度时也有一个技巧,我将在下面的代码中解释:
UserControl.xaml.cs (别忘了.ZERO "000.0)
直接设置 SubMenu
的宽度将改变其 header 而不是菜单本身。同样更改 SubItems 的宽度也不会解决问题,因为错误出在 Popup 本身而不是它的项目中。要解决这个问题,您可以使用 VisualTreeHelper.GetChild(DependencyObject, Int32) Method 直到到达 Popup 并直接更改其宽度,或者您可以按照以下步骤操作:
private void Menu_Opened(object sender, RoutedEventArgs e)
{
if (Languages.Language == "English")
{
Menu.Width = 183;
SubMenu.Tag = 137.0;
}
else if (Languages.Language == "العربية")
{
Menu.Width = 123;
SubMenu.Tag = 117.0;
}
}
(MenuItem.SubmenuHeaderTemplateKey) 模板位于 App.xaml:
<Popup x:Name="Popup" Width="{Binding Tag, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=MenuItem}}" Placement="Right" HorizontalOffset="-4" IsOpen="{TemplateBinding IsSubmenuOpen}" AllowsTransparency="True" Focusable="False" PopupAnimation="Fade">
完整模板
<ControlTemplate x:Key="{x:Static MenuItem.SubmenuHeaderTemplateKey}" TargetType="{x:Type MenuItem}">
<Border Name="Border" CornerRadius="4" Margin="1" Height="25">
<Grid Margin="0,0,5,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="25"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="20"/>
</Grid.ColumnDefinitions>
<Path Grid.Column="0" FlowDirection="LeftToRight" Stretch="Uniform" Margin="0,5.5,0,5.5" Fill="{DynamicResource ForegroundBrush}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" HorizontalAlignment="Center" Data="{Binding Uid, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=MenuItem}}"/>
<ContentPresenter x:Name="HeaderHost" Grid.Column="1" ContentSource="Header" RecognizesAccessKey="True" VerticalAlignment="Center" TextElement.FontFamily="{StaticResource Segoe Semibold}" TextElement.FontSize="13.5" TextElement.Foreground="{DynamicResource ForegroundBrush}"/>
<Path Grid.Column="2" Margin="12,6,0,6" Stretch="Uniform" VerticalAlignment="Center" Fill="{DynamicResource ForegroundBrush}" Data="M 0 0 L 0 7 L 4 3.5 Z"/>
<Popup x:Name="Popup" Width="{Binding Tag, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=MenuItem}}" Placement="Right" HorizontalOffset="-4" IsOpen="{TemplateBinding IsSubmenuOpen}" AllowsTransparency="True" Focusable="False" PopupAnimation="Fade">
<Grid>
<Border Margin="2" CornerRadius="4" BorderThickness="0" Background="{DynamicResource CardBrush}" Effect="{DynamicResource FluentDropShadowEffect}"/>
<StackPanel Margin="4" IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Cycle"/>
</Grid>
</Popup>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Border" Property="Background" Value="{DynamicResource ElementHoverBrush}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.5"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
我正在开发一个 wpf .net core 5 应用程序。该应用程序支持多语言。此应用有 UserControl
和 ContextMenu
。
问题: 第一次打开上下文菜单时,它适合其内容的宽度,这是正常的。但是当更改应用程序语言并再次打开菜单时,它的宽度保持不变。这隐藏了它的内容!
备注: 如果应用程序以 语言 A 启动,然后语言更改为 语言 B.. 打开菜单时它适合 语言B内容反之
我认为这是 UI 引擎的一个错误。但是解决此问题的最佳方法是什么而不是手动设置菜单的宽度 OnContextMenuOpening
固定宽度根据当前语言?或者它如何在第一次渲染它的大小,以便我每次打开时都可以这样调用?
截图1
截图2
答案
经过数小时的搜索后,我无法找到无需手动设置宽度即可修复此错误的方法。即使是手动方式在设置子菜单项的宽度时也有一个技巧,我将在下面的代码中解释:
UserControl.xaml.cs (别忘了.ZERO "000.0)
直接设置 SubMenu
的宽度将改变其 header 而不是菜单本身。同样更改 SubItems 的宽度也不会解决问题,因为错误出在 Popup 本身而不是它的项目中。要解决这个问题,您可以使用 VisualTreeHelper.GetChild(DependencyObject, Int32) Method 直到到达 Popup 并直接更改其宽度,或者您可以按照以下步骤操作:
private void Menu_Opened(object sender, RoutedEventArgs e)
{
if (Languages.Language == "English")
{
Menu.Width = 183;
SubMenu.Tag = 137.0;
}
else if (Languages.Language == "العربية")
{
Menu.Width = 123;
SubMenu.Tag = 117.0;
}
}
(MenuItem.SubmenuHeaderTemplateKey) 模板位于 App.xaml:
<Popup x:Name="Popup" Width="{Binding Tag, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=MenuItem}}" Placement="Right" HorizontalOffset="-4" IsOpen="{TemplateBinding IsSubmenuOpen}" AllowsTransparency="True" Focusable="False" PopupAnimation="Fade">
完整模板
<ControlTemplate x:Key="{x:Static MenuItem.SubmenuHeaderTemplateKey}" TargetType="{x:Type MenuItem}">
<Border Name="Border" CornerRadius="4" Margin="1" Height="25">
<Grid Margin="0,0,5,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="25"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="20"/>
</Grid.ColumnDefinitions>
<Path Grid.Column="0" FlowDirection="LeftToRight" Stretch="Uniform" Margin="0,5.5,0,5.5" Fill="{DynamicResource ForegroundBrush}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" HorizontalAlignment="Center" Data="{Binding Uid, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=MenuItem}}"/>
<ContentPresenter x:Name="HeaderHost" Grid.Column="1" ContentSource="Header" RecognizesAccessKey="True" VerticalAlignment="Center" TextElement.FontFamily="{StaticResource Segoe Semibold}" TextElement.FontSize="13.5" TextElement.Foreground="{DynamicResource ForegroundBrush}"/>
<Path Grid.Column="2" Margin="12,6,0,6" Stretch="Uniform" VerticalAlignment="Center" Fill="{DynamicResource ForegroundBrush}" Data="M 0 0 L 0 7 L 4 3.5 Z"/>
<Popup x:Name="Popup" Width="{Binding Tag, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=MenuItem}}" Placement="Right" HorizontalOffset="-4" IsOpen="{TemplateBinding IsSubmenuOpen}" AllowsTransparency="True" Focusable="False" PopupAnimation="Fade">
<Grid>
<Border Margin="2" CornerRadius="4" BorderThickness="0" Background="{DynamicResource CardBrush}" Effect="{DynamicResource FluentDropShadowEffect}"/>
<StackPanel Margin="4" IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Cycle"/>
</Grid>
</Popup>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Border" Property="Background" Value="{DynamicResource ElementHoverBrush}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.5"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>