我制作了一个自定义 WPF
ContextMenu
,以在菜单顶部或底部的条带中显示按钮,就像 Windows 11 资源管理器上下文菜单中的复制/粘贴按钮一样。
一切正常,但在调试输出窗口中我收到以下错误:
System.Windows.Data 错误:4:找不到绑定源 参考'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.ItemsControl', 祖先等级='1''。 BindingExpression:Path=HorizontalContentAlignment; 数据项=空;目标元素是“MenuItem”(名称=“”);目标财产 是“HorizontalContentAlignment”(类型“HorizontalAlignment”)
System.Windows.Data 错误:4:找不到绑定源 参考'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.ItemsControl', 祖先等级='1''。 BindingExpression:Path=VerticalContentAlignment; 数据项=空;目标元素是“MenuItem”(名称=“”);目标财产 是“VerticalContentAlignment”(类型“VerticalAlignment”)
我能做些什么来让这些消失吗?我什至尝试过为
MenuItem
定义自定义样式和模板,但肯定不会尝试找到 ItemsControl
来获取 HorizontalContentAlignment
和 VerticalContentAlignment
属性,那么这是从哪里来的呢?
这是我的自定义的 XAML
ContextMenu
:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:Laila.Shell.Controls">
<Style TargetType="{x:Type controls:ContextMenu}">
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Grid.IsSharedSizeScope" Value="true" />
<Setter Property="Foreground" Value="Black" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type controls:ContextMenu}">
<Border Padding="3" x:Name="PART_Menu" Opacity="0" BorderBrush="#999999" BorderThickness="1"
Background="#F0F0F0" Margin="0,0,6,6" UseLayoutRounding="True" SnapsToDevicePixels="True">
<Border.Triggers>
<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:0.2" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_Menu" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Border.Triggers>
<Border.Effect>
<DropShadowEffect BlurRadius="3" Color="Black" ShadowDepth="3" Opacity="0.5" />
</Border.Effect>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Border x:Name="borderTop" Grid.Row="0" Background="#dfdfdf" Padding="2" Visibility="Visible">
<StackPanel Orientation="Horizontal" x:Name="PART_ButtonsTop" />
</Border>
<ScrollViewer Grid.Row="1" x:Name="PART_ScrollViewer"
HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Auto">
<ItemsPresenter Margin="0,0,0,1" x:Name="PART_ItemsPresenter" />
</ScrollViewer>
<Border x:Name="borderBottom" Grid.Row="2" Background="#dfdfdf" Padding="2" Visibility="Visible">
<StackPanel Orientation="Horizontal" x:Name="PART_ButtonsBottom" />
</Border>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="ShowButtonsTopOrBottom" Value="Bottom">
<Setter Property="Visibility" TargetName="borderTop" Value="Collapsed" />
</Trigger>
<Trigger Property="ShowButtonsTopOrBottom" Value="None">
<Setter Property="Visibility" TargetName="borderTop" Value="Collapsed" />
</Trigger>
<Trigger Property="ShowButtonsTopOrBottom" Value="Top">
<Setter Property="Visibility" TargetName="borderBottom" Value="Collapsed" />
</Trigger>
<Trigger Property="ShowButtonsTopOrBottom" Value="None">
<Setter Property="Visibility" TargetName="borderBottom" Value="Collapsed" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
编辑:这些是我的菜单项的样式和模板:
<SolidColorBrush x:Key="Menu.BorderBrush" Color="#999999"/>
<SolidColorBrush x:Key="Menu.Background" Color="#F0F0F0"/>
<SolidColorBrush x:Key="Menu.Foreground" Color="Black"/>
<SolidColorBrush x:Key="MenuItem.Highlighted.BorderBrush" Color="#26A0DA"/>
<SolidColorBrush x:Key="MenuItem.Highlighted.Background" Color="#C0DDEB"/>
<SolidColorBrush x:Key="MenuItem.Highlighted.Foreground" Color="Black"/>
<SolidColorBrush x:Key="MenuItem.Disabled.Foreground" Color="Gray"/>
<Style x:Key="{x:Static MenuItem.SeparatorStyleKey}" TargetType="{x:Type Separator}">
<Setter Property="Margin" Value="-10,0,0,0" />
</Style>
<Style TargetType="{x:Type Menu}">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="{StaticResource Menu.Foreground}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Menu}">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}"
SnapsToDevicePixels="true">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ControlTemplate x:Key="{ComponentResourceKey ResourceId=SubmenuItemTemplateKey, TypeInTargetAssembly={x:Type MenuItem}}" TargetType="{x:Type MenuItem}">
<Grid SnapsToDevicePixels="true">
<Border x:Name="Bg" BorderThickness="1" Background="Transparent" />
<Grid Height="22">
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="MenuItemCheckColumnGroup" Width="Auto"/>
<ColumnDefinition SharedSizeGroup="MenuItemIconColumnGroup" Width="Auto"/>
<ColumnDefinition Width="4"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="37"/>
<ColumnDefinition SharedSizeGroup="MenuItemIGTColumnGroup" Width="Auto"/>
<ColumnDefinition Width="17"/>
</Grid.ColumnDefinitions>
<Border x:Name="GlyphPanel" Height="20" Margin="1" Visibility="Collapsed" Width="22">
<Image x:Name="Glyph" Width="16" Height="16" Source="pack://application:,,,/Laila.Shell;component/Images/check16.png" />
</Border>
<ContentPresenter Grid.Column="1" x:Name="Icon" Height="16" Width="16" ContentSource="Icon" Margin="4,1,1,1" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="Center"/>
<ContentPresenter Grid.Column="3" ContentSource="Header" VerticalAlignment="Center" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
<TextBlock Grid.Column="5" Margin="{TemplateBinding Padding}" VerticalAlignment="Center" Text="{TemplateBinding InputGestureText}"/>
</Grid>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="Icon" Value="{x:Null}">
<Setter Property="Visibility" TargetName="Icon" Value="Collapsed"/>
</Trigger>
<Trigger Property="IsCheckable" Value="true">
<Setter Property="Visibility" TargetName="GlyphPanel" Value="Hidden"/>
</Trigger>
<Trigger Property="IsChecked" Value="true">
<Setter Property="Visibility" TargetName="GlyphPanel" Value="Visible"/>
</Trigger>
<Trigger Property="IsHighlighted" Value="true">
<Setter Property="Foreground" Value="{StaticResource MenuItem.Highlighted.Foreground}"/>
<Setter Property="Background" TargetName="Bg" Value="{StaticResource MenuItem.Highlighted.Background}"/>
<Setter Property="BorderBrush" TargetName="Bg" Value="{StaticResource MenuItem.Highlighted.BorderBrush}" />
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{StaticResource MenuItem.Disabled.Foreground}"/>
<Setter Property="Opacity" TargetName="Glyph" Value="0.30"/>
<Setter Property="Opacity" TargetName="Icon" Value="0.30"/>
</Trigger>
<Trigger Property="IsPressed" Value="true">
<Setter Property="Foreground" Value="{StaticResource MenuItem.Highlighted.Foreground}"/>
<Setter Property="Background" TargetName="Bg" Value="{StaticResource MenuItem.Highlighted.Background}"/>
<Setter Property="BorderBrush" TargetName="Bg" Value="{StaticResource MenuItem.Highlighted.BorderBrush}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<ControlTemplate x:Key="{ComponentResourceKey ResourceId=SubmenuContent, TypeInTargetAssembly={x:Type FrameworkElement}}" TargetType="{x:Type ContentControl}">
<Border Padding="3" x:Name="PART_Menu" Opacity="0" BorderBrush="{StaticResource Menu.BorderBrush}"
BorderThickness="1" Background="{StaticResource Menu.Background}" Margin="0,0,6,6">
<Border.Triggers>
<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:0.2" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_Menu" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Border.Triggers>
<Border.Effect>
<DropShadowEffect BlurRadius="3" Color="Black" ShadowDepth="3" Opacity="0.5" />
</Border.Effect>
<ScrollViewer x:Name="PART_ScrollViewer"
HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Auto">
<ContentPresenter />
</ScrollViewer>
</Border>
</ControlTemplate>
<ControlTemplate x:Key="{ComponentResourceKey ResourceId=TopLevelHeaderTemplateKey, TypeInTargetAssembly={x:Type MenuItem}}" TargetType="{x:Type MenuItem}">
<Grid SnapsToDevicePixels="true">
<Border x:Name="Bg" Background="{TemplateBinding Background}" BorderThickness="1">
<StackPanel Orientation="Horizontal">
<ContentPresenter x:Name="Icon" ContentSource="Icon" Margin="4,0,6,0" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="Center"/>
<Image x:Name="GlyphPanel" Width="16" Height="16" Source="pack://application:,,,/Laila.Shell;component/Images/check16.png" Margin="7,0,0,0" Visibility="Collapsed" VerticalAlignment="Center" />
<ContentPresenter ContentSource="Header" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</StackPanel>
</Border>
<Popup x:Name="PART_Popup" AllowsTransparency="true" Focusable="false" HorizontalOffset="1" IsOpen="{Binding IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}" PopupAnimation="{DynamicResource {x:Static SystemParameters.MenuPopupAnimationKey}}" Placement="Bottom" VerticalOffset="-1">
<Border>
<ContentControl x:Name="SubMenuBorder" IsTabStop="false" Template="{DynamicResource {ComponentResourceKey ResourceId=SubmenuContent, TypeInTargetAssembly={x:Type FrameworkElement}}}">
<ScrollViewer x:Name="PART_ScrollViewer"
HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Auto">
<Grid RenderOptions.ClearTypeHint="Enabled">
<ItemsPresenter x:Name="ItemsPresenter" KeyboardNavigation.DirectionalNavigation="Cycle" Grid.IsSharedSizeScope="true" Margin="2" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" KeyboardNavigation.TabNavigation="Cycle"/>
</Grid>
</ScrollViewer>
</ContentControl>
</Border>
</Popup>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="Icon" Value="{x:Null}">
<Setter Property="Visibility" TargetName="Icon" Value="Collapsed"/>
</Trigger>
<Trigger Property="IsChecked" Value="true">
<Setter Property="Visibility" TargetName="GlyphPanel" Value="Visible"/>
<Setter Property="Visibility" TargetName="Icon" Value="Collapsed"/>
</Trigger>
<Trigger Property="IsHighlighted" Value="true">
<Setter Property="Foreground" Value="{StaticResource MenuItem.Highlighted.Foreground}"/>
<Setter Property="Background" TargetName="Bg" Value="{StaticResource MenuItem.Highlighted.Background}"/>
<Setter Property="BorderBrush" TargetName="Bg" Value="{StaticResource MenuItem.Highlighted.BorderBrush}" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="true">
<Setter Property="Foreground" Value="{StaticResource MenuItem.Highlighted.Foreground}"/>
<Setter Property="Background" TargetName="Bg" Value="{StaticResource MenuItem.Highlighted.Background}"/>
<Setter Property="BorderBrush" TargetName="Bg" Value="{StaticResource MenuItem.Highlighted.BorderBrush}" />
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{StaticResource MenuItem.Disabled.Foreground}"/>
<Setter Property="Opacity" TargetName="GlyphPanel" Value="0.30"/>
<Setter Property="Opacity" TargetName="Icon" Value="0.30"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<ControlTemplate x:Key="{ComponentResourceKey ResourceId=TopLevelItemTemplateKey, TypeInTargetAssembly={x:Type MenuItem}}" TargetType="{x:Type MenuItem}">
<Grid SnapsToDevicePixels="true">
<Border x:Name="Bg" BorderThickness="1" Background="Transparent"/>
<DockPanel>
<ContentPresenter x:Name="Icon" ContentSource="Icon" Margin="4,0,6,0" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="Center"/>
<Image x:Name="GlyphPanel" Width="16" Height="16" Source="pack://application:,,,/Laila.Shell;component/Images/check16.png" Margin="7,0,0,0" Visibility="Collapsed" VerticalAlignment="Center" />
<ContentPresenter ContentSource="Header" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</DockPanel>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="Icon" Value="{x:Null}">
<Setter Property="Visibility" TargetName="Icon" Value="Collapsed"/>
</Trigger>
<Trigger Property="IsChecked" Value="true">
<Setter Property="Visibility" TargetName="GlyphPanel" Value="Visible"/>
<Setter Property="Visibility" TargetName="Icon" Value="Collapsed"/>
</Trigger>
<Trigger Property="IsHighlighted" Value="true">
<Setter Property="Foreground" Value="{StaticResource MenuItem.Highlighted.Foreground}"/>
<Setter Property="Background" TargetName="Bg" Value="{StaticResource MenuItem.Highlighted.Background}"/>
<Setter Property="BorderBrush" TargetName="Bg" Value="{StaticResource MenuItem.Highlighted.BorderBrush}" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="true">
<Setter Property="Foreground" Value="{StaticResource MenuItem.Highlighted.Foreground}"/>
<Setter Property="Background" TargetName="Bg" Value="{StaticResource MenuItem.Highlighted.Background}"/>
<Setter Property="BorderBrush" TargetName="Bg" Value="{StaticResource MenuItem.Highlighted.BorderBrush}" />
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{StaticResource MenuItem.Disabled.Foreground}"/>
<Setter Property="Opacity" TargetName="GlyphPanel" Value="0.30"/>
<Setter Property="Opacity" TargetName="Icon" Value="0.30"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<Geometry x:Key="RightArrow">M 0,0 L 4,3.5 L 0,7 Z</Geometry>
<ControlTemplate x:Key="{ComponentResourceKey ResourceId=SubmenuHeaderTemplateKey, TypeInTargetAssembly={x:Type MenuItem}}" TargetType="{x:Type MenuItem}">
<Grid SnapsToDevicePixels="true">
<Border x:Name="Bg" BorderThickness="1" Background="Transparent"/>
<Grid Height="22">
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="MenuItemCheckColumnGroup" Width="Auto"/>
<ColumnDefinition SharedSizeGroup="MenuItemIconColumnGroup" Width="Auto"/>
<ColumnDefinition Width="4"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="37"/>
<ColumnDefinition SharedSizeGroup="MenuItemIGTColumnGroup" Width="Auto"/>
<ColumnDefinition Width="17"/>
</Grid.ColumnDefinitions>
<Border x:Name="GlyphPanel" BorderBrush="#CDD3E6" BorderThickness="1" Background="#E6EFF4" CornerRadius="3" Height="20" Margin="1" Visibility="Collapsed" Width="22">
<Image x:Name="Glyph" Width="16" Height="16" Source="pack://application:,,,/Laila.Shell;component/Images/check16.png" />
</Border>
<ContentPresenter Grid.Column="1" x:Name="Icon" Height="16" Width="16" ContentSource="Icon" Margin="4,1,1,1" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="Center"/>
<ContentPresenter Grid.Column="3" ContentSource="Header" VerticalAlignment="Center" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
<TextBlock Grid.Column="5" Margin="{TemplateBinding Padding}" VerticalAlignment="Center" Text="{TemplateBinding InputGestureText}" Visibility="Collapsed"/>
<Path Grid.Column="6" Data="{StaticResource RightArrow}" Fill="{TemplateBinding Foreground}" Margin="4,0,0,0" VerticalAlignment="Center"/>
</Grid>
<Popup x:Name="PART_Popup" AllowsTransparency="true" Focusable="false" HorizontalOffset="-2" IsOpen="{Binding IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}" PopupAnimation="{DynamicResource {x:Static SystemParameters.MenuPopupAnimationKey}}" Placement="Right" VerticalOffset="-3">
<ContentControl x:Name="SubMenuBorder" IsTabStop="false" Template="{DynamicResource {ComponentResourceKey ResourceId=SubmenuContent, TypeInTargetAssembly={x:Type FrameworkElement}}}">
<ScrollViewer x:Name="PART_ScrollViewer"
HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Auto">
<Grid RenderOptions.ClearTypeHint="Enabled">
<ItemsPresenter x:Name="ItemsPresenter" KeyboardNavigation.DirectionalNavigation="Cycle" Grid.IsSharedSizeScope="true" Margin="2" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" KeyboardNavigation.TabNavigation="Cycle"/>
</Grid>
</ScrollViewer>
</ContentControl>
</Popup>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="Icon" Value="{x:Null}">
<Setter Property="Visibility" TargetName="Icon" Value="Collapsed"/>
</Trigger>
<Trigger Property="IsCheckable" Value="true">
<Setter Property="Visibility" TargetName="GlyphPanel" Value="Hidden"/>
</Trigger>
<Trigger Property="IsChecked" Value="true">
<Setter Property="Visibility" TargetName="GlyphPanel" Value="Visible"/>
</Trigger>
<Trigger Property="IsHighlighted" Value="true">
<Setter Property="Foreground" Value="{StaticResource MenuItem.Highlighted.Foreground}"/>
<Setter Property="Background" TargetName="Bg" Value="{StaticResource MenuItem.Highlighted.Background}"/>
<Setter Property="BorderBrush" TargetName="Bg" Value="{StaticResource MenuItem.Highlighted.BorderBrush}" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="true">
<Setter Property="Foreground" Value="{StaticResource MenuItem.Highlighted.Foreground}"/>
<Setter Property="Background" TargetName="Bg" Value="{StaticResource MenuItem.Highlighted.Background}"/>
<Setter Property="BorderBrush" TargetName="Bg" Value="{StaticResource MenuItem.Highlighted.BorderBrush}" />
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{StaticResource MenuItem.Disabled.Foreground}"/>
<Setter Property="Opacity" TargetName="GlyphPanel" Value="0.30"/>
<Setter Property="Opacity" TargetName="Icon" Value="0.30"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
显然这是由默认的
MenuItem
样式引起的,该样式尚未适应,因为我只是为不同类型的ControlTemplate
重新定义了MenuItem
。
我通过将其添加到我的应用程序范围样式中来摆脱这些消息:
<Style TargetType="{x:Type MenuItem}">
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
</Style>