WPF 菜单 - 允许在禁用的菜单项中启用特定控件
WPF Menu - Allow specific control to be enabled inside disabled menuitem
我有一个绑定到 collection 模型的菜单。
MenuItem 命令绑定到模型命令。
我重新定义了 SubMenuItem 控件模板以在其中添加一个 ToggleButton。
此 ToggleButton 允许用户将 MenuItem 指定为“收藏夹”。我希望此 ToggleButton 始终处于启用状态。
<ControlTemplate x:Key="{x:Static MenuItem.SubmenuItemTemplateKey}" TargetType="{x:Type MenuItem}">
<Grid x:Name="PART_Conteneur" Background="Transparent">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="Star" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ToggleButton x:Name="PART_StarButton" Style="{DynamicResource VerticalToolBarMenuStarToggleButtonStyle}" VerticalAlignment="Center" Margin="2,0,0,0" />
<Border x:Name="Border" BorderThickness="1" Grid.Column="1" Padding="0,2,0,2">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="Icon" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" SharedSizeGroup="Shortcut" />
<ColumnDefinition Width="13" />
</Grid.ColumnDefinitions>
<ContentPresenter x:Name="Icon" Margin="6,0,6,0" VerticalAlignment="Center" Grid.Column="0" ContentSource="Icon" Width="20" />
<ContentPresenter x:Name="HeaderHost" Grid.Column="1" ContentSource="Header" RecognizesAccessKey="True" VerticalAlignment="Center" />
<TextBlock x:Name="InputGestureText" Grid.Column="2" Text="{TemplateBinding InputGestureText}" Margin="5,2,0,2" DockPanel.Dock="Right" />
</Grid>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="ButtonBase.Command" Value="{x:Null}" />
<Trigger Property="Icon" Value="{x:Null}">
<Setter TargetName="Icon" Property="Visibility" Value="Hidden" />
</Trigger>
<Trigger Property="IsHighlighted" Value="true">
<Setter Property="Background" TargetName="Border" Value="{DynamicResource ItemSelectedBrushKey}" />
<Setter Property="BorderBrush" TargetName="Border">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF888888" Offset="0" />
<GradientStop Color="Transparent" Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Opacity" Value="{DynamicResource DisableOpacity}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
当 MenuItem 被禁用时(Command CanExecute returns False),ToggleButton 也被禁用。
如何才能只启用 ToggleButton?
编辑:
我设法通过在将包含切换按钮的 TopLevelHeader 模板弹出窗口中添加一个新的 ItemsControl 来满足我的需求:
<ControlTemplate x:Key="VerticalToolBarMenuTopLevelHeaderTemplate" TargetType="{x:Type MenuItem}">
<Border x:Name="Border">
<Grid>
<ContentPresenter Margin="6,3,20,3" ContentSource="Header" RecognizesAccessKey="True" HorizontalAlignment="Right" />
<Popup x:Name="Popup" Placement="Bottom" IsOpen="{TemplateBinding IsSubmenuOpen}" AllowsTransparency="True" Focusable="False" PopupAnimation="Fade" StaysOpen="True">
<Border x:Name="SubmenuBorder" SnapsToDevicePixels="True" BorderThickness="1" Background="{DynamicResource ToolBarPopupBackgroundBrushKey}"
BorderBrush="{DynamicResource PopupBorderBrushKey}">
<ScrollViewer CanContentScroll="True" VerticalScrollBarVisibility="Auto">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ItemsControl ItemsSource="{Binding }">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Height="25">
<ToggleButton x:Name="PART_StarButton" Style="{DynamicResource VerticalToolBarMenuStarToggleButtonStyle}" VerticalAlignment="Center" Margin="2,0,0,0" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Cycle" Grid.Column="1" />
</Grid>
</ScrollViewer>
</Border>
</Popup>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSuspendingPopupAnimation" Value="true">
<Setter TargetName="Popup" Property="PopupAnimation" Value="None" />
</Trigger>
<Trigger Property="IsHighlighted" Value="true">
<Setter TargetName="Border" Property="BorderBrush" Value="Transparent" />
<Setter Property="Background" TargetName="Border" Value="{DynamicResource ItemSelectedBrushKey}" />
</Trigger>
<Trigger SourceName="Popup" Property="AllowsTransparency" Value="True">
<Setter TargetName="SubmenuBorder" Property="CornerRadius" Value="0,0,4,4" />
<Setter TargetName="SubmenuBorder" Property="Padding" Value="0,0,0,3" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="{DynamicResource DisableOpacity}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
不,你不能这样做。
当 CanExecute returns 为 false 时,IsEnabled 属性 将采用相同的值。
IsEnabled = false 不仅禁用元素本身,还禁用嵌套在其中的所有内容。
此行为在 UIElement 中定义,无法更改。
我有一个绑定到 collection 模型的菜单。 MenuItem 命令绑定到模型命令。
我重新定义了 SubMenuItem 控件模板以在其中添加一个 ToggleButton。 此 ToggleButton 允许用户将 MenuItem 指定为“收藏夹”。我希望此 ToggleButton 始终处于启用状态。
<ControlTemplate x:Key="{x:Static MenuItem.SubmenuItemTemplateKey}" TargetType="{x:Type MenuItem}">
<Grid x:Name="PART_Conteneur" Background="Transparent">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="Star" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ToggleButton x:Name="PART_StarButton" Style="{DynamicResource VerticalToolBarMenuStarToggleButtonStyle}" VerticalAlignment="Center" Margin="2,0,0,0" />
<Border x:Name="Border" BorderThickness="1" Grid.Column="1" Padding="0,2,0,2">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="Icon" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" SharedSizeGroup="Shortcut" />
<ColumnDefinition Width="13" />
</Grid.ColumnDefinitions>
<ContentPresenter x:Name="Icon" Margin="6,0,6,0" VerticalAlignment="Center" Grid.Column="0" ContentSource="Icon" Width="20" />
<ContentPresenter x:Name="HeaderHost" Grid.Column="1" ContentSource="Header" RecognizesAccessKey="True" VerticalAlignment="Center" />
<TextBlock x:Name="InputGestureText" Grid.Column="2" Text="{TemplateBinding InputGestureText}" Margin="5,2,0,2" DockPanel.Dock="Right" />
</Grid>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="ButtonBase.Command" Value="{x:Null}" />
<Trigger Property="Icon" Value="{x:Null}">
<Setter TargetName="Icon" Property="Visibility" Value="Hidden" />
</Trigger>
<Trigger Property="IsHighlighted" Value="true">
<Setter Property="Background" TargetName="Border" Value="{DynamicResource ItemSelectedBrushKey}" />
<Setter Property="BorderBrush" TargetName="Border">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF888888" Offset="0" />
<GradientStop Color="Transparent" Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Opacity" Value="{DynamicResource DisableOpacity}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
当 MenuItem 被禁用时(Command CanExecute returns False),ToggleButton 也被禁用。
如何才能只启用 ToggleButton?
编辑:
我设法通过在将包含切换按钮的 TopLevelHeader 模板弹出窗口中添加一个新的 ItemsControl 来满足我的需求:
<ControlTemplate x:Key="VerticalToolBarMenuTopLevelHeaderTemplate" TargetType="{x:Type MenuItem}">
<Border x:Name="Border">
<Grid>
<ContentPresenter Margin="6,3,20,3" ContentSource="Header" RecognizesAccessKey="True" HorizontalAlignment="Right" />
<Popup x:Name="Popup" Placement="Bottom" IsOpen="{TemplateBinding IsSubmenuOpen}" AllowsTransparency="True" Focusable="False" PopupAnimation="Fade" StaysOpen="True">
<Border x:Name="SubmenuBorder" SnapsToDevicePixels="True" BorderThickness="1" Background="{DynamicResource ToolBarPopupBackgroundBrushKey}"
BorderBrush="{DynamicResource PopupBorderBrushKey}">
<ScrollViewer CanContentScroll="True" VerticalScrollBarVisibility="Auto">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ItemsControl ItemsSource="{Binding }">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Height="25">
<ToggleButton x:Name="PART_StarButton" Style="{DynamicResource VerticalToolBarMenuStarToggleButtonStyle}" VerticalAlignment="Center" Margin="2,0,0,0" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Cycle" Grid.Column="1" />
</Grid>
</ScrollViewer>
</Border>
</Popup>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSuspendingPopupAnimation" Value="true">
<Setter TargetName="Popup" Property="PopupAnimation" Value="None" />
</Trigger>
<Trigger Property="IsHighlighted" Value="true">
<Setter TargetName="Border" Property="BorderBrush" Value="Transparent" />
<Setter Property="Background" TargetName="Border" Value="{DynamicResource ItemSelectedBrushKey}" />
</Trigger>
<Trigger SourceName="Popup" Property="AllowsTransparency" Value="True">
<Setter TargetName="SubmenuBorder" Property="CornerRadius" Value="0,0,4,4" />
<Setter TargetName="SubmenuBorder" Property="Padding" Value="0,0,0,3" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="{DynamicResource DisableOpacity}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
不,你不能这样做。 当 CanExecute returns 为 false 时,IsEnabled 属性 将采用相同的值。 IsEnabled = false 不仅禁用元素本身,还禁用嵌套在其中的所有内容。 此行为在 UIElement 中定义,无法更改。