我从this site获取ContextMenu
的隐式样式:
<Application.Resources>
<SolidColorBrush x:Key="WindowBackgroundBrush" Color="#FFF" />
<SolidColorBrush x:Key="SolidBorderBrush" Color="#888" />
<Style TargetType="ContextMenu">
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="Grid.IsSharedSizeScope" Value="true"/>
<Setter Property="HasDropShadow" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContextMenu">
<Border
Name="Border"
Background="{StaticResource WindowBackgroundBrush}"
BorderBrush="{StaticResource SolidBorderBrush}"
BorderThickness="1" >
<StackPanel IsItemsHost="True"
KeyboardNavigation.DirectionalNavigation="Cycle"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="HasDropShadow" Value="true">
<Setter TargetName="Border" Property="Padding" Value="0,3,0,3"/>
<Setter TargetName="Border" Property="CornerRadius" Value="4"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Application.Resources>
然后我尝试在此处使用它,因此它同时适用于ContextMenu
的默认TextBox
和我为ContextMenu
添加的Button
。
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBox Height="30" Width="200">Test</TextBox>
<Button Grid.Row="1" Width="200" Height="30" Content="Test2">
<Button.ContextMenu>
<ContextMenu>
<MenuItem>Test</MenuItem>
<MenuItem>Test2</MenuItem>
</ContextMenu>
</Button.ContextMenu>
</Button>
</Grid>
该样式应用于Button
,但未应用于TextBox
。
我觉得这应该是相当简单和简单的,为什么我的隐式样式不适用于ContextMenu
的默认TextBox
,我做错了什么?
==更新==
我目前还不确定答案,但我认为这里的问题是TextBox
与ContextMenu
的设计中的一些缺陷,我希望有更多知识渊博的人能够证实。
使用Snoop我可以看到ContextMenu
不是你期望的对象,而是EditorContextMenu
对象,它是内部的,所以你不能设置它的样式。他们为什么要这样用?我不知道。
作为一种解决方法,我创建了一个默认的上下文菜单并使用它。如果向TextBox
添加上下文菜单,则它会正确地采用隐式样式。
既然您知道默认ContextMenu
具有的项目,并且项目依次使用ApplicationCommands,则非常简单:
<ContextMenu x:Key="DefaultContextMenu">
<MenuItem Command="ApplicationCommands.Copy" />
<MenuItem Command="ApplicationCommands.Cut" />
<MenuItem Command="ApplicationCommands.Paste" />
</ContextMenu>
然后在TextBoxStyle中执行:
<Style x:Key="MyTextBoxStyle" TargetType="TextBox">
<Setter Property="ContextMenu" Value="{StaticResource DefaultContextMenu}" />
有了这个,TextBox
的默认ContextMenu
将采用隐式格式。
答案 0 :(得分:0)
对我来说,这似乎是TextBox
实现中的一个错误,其独特之处在于ContextMenu
不属于VisualTree。
我会尽力解释。
ContextMenu
并由TextBox
显示
实现,即方法
OnContextMenuOpening(ContextMenuEventArgs e)
。要看到它,你可以
在自定义TextBox
中重写此方法,并省略base.
调用。ContextMenu
相比,默认ContextMenu
为
(不通过ContextMenuService
处理)。ContextMenu
才会创建默认TextBox
:
没有明确设置TextBox.ContextMenu
属性(XAML或后面的代码)。ContextMenu
不在VisualTree中,并且是与
VisualTree是属性PlacementTarget
(例如,如果要创建
并在后面的代码中打开ContextMenu
,并且不要设置
PlacementTarget
隐式样式将不会应用。)TextBox
实现中,设置了ContextMenu.PlacementTarget
,但该值来自某些内部缓存/字典。我不能
调试并确定地说,但是我想缓存的值是错误的
这里。 OnContextMenuOpening(ContextMenuEventArgs e)
TextBox
,并且在调用基本函数之前,请先修改
TextBox
(例如,每次设置另一个Margin
)。默认的ContextMenu
甚至不会打开!如果您代替base
通话,请实例化并显示
ContextMenu
,然后进行Margin
修改
不会打扰,打开的ContextMenu
将具有您在资源中设置的隐式样式。要测试的代码段:
public class MyStyledTextBox: TextBox
{
protected override void OnContextMenuOpening(ContextMenuEventArgs e)
{
//this.Margin = new Thickness(0, 20, 0, 0);
var uiScope = e.Source as TextBox;
var ctxm = new ContextMenu();
MenuItem menuItem;
menuItem = new MenuItem();
menuItem.Header = "CutCustom";
menuItem.CommandTarget = this;
menuItem.Command = ApplicationCommands.Cut;
ctxm.Items.Add(menuItem);
ctxm.PlacementTarget = uiScope;
ctxm.IsOpen = true;
//base.OnContextMenuOpening(e);
}
}
<StackPanel>
<StackPanel.Resources>
<Style TargetType="ContextMenu" >
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="Grid.IsSharedSizeScope" Value="true"/>
<Setter Property="HasDropShadow" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContextMenu">
<Border Name="Border_custom" Background="Chocolate" BorderBrush="Coral" BorderThickness="1" >
<StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Cycle"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="HasDropShadow" Value="true">
<Setter TargetName="Border_custom" Property="Padding" Value="0,3,0,3"/>
<Setter TargetName="Border_custom" Property="CornerRadius" Value="4"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</StackPanel.Resources>
<local:MyStyledTextBox Height="30" Width="200" Text="Test">
<!--<TextBox.ContextMenu>
<ContextMenu>
<MenuItem Header="Test"/>
<MenuItem Header="Test2"/>
</ContextMenu>
</TextBox.ContextMenu>-->
</local:MyStyledTextBox>
</StackPanel>
我说的是关于bug的问题,因为默认情况下ScrollBar
的{{1}}实现确实正确地应用了隐式样式。
坏消息是,在ContextMenu
的当前实现中,您无法达到内部创建的默认TextBox
且隐式样式未被应用。