WPF MenuItem样式未应用于TextBox上下文菜单中

时间:2016-01-21 09:42:55

标签: wpf xaml textbox menuitem wpf-style

我曾经创建过一种样式来修复WPF中菜单项的错误外观。它主要是关于未对齐的菜单文本。它在左上角太远,没有使用适当的间距。

我发现它在窗口菜单中有效,但在TextBox的上下文菜单中,我现在测试了它。所以问题是,为什么这种风格不是从文本框中考虑上下文菜单?

更新:我发现TextBox使用自己的菜单项类,私有嵌套类TextEditorContextMenu.EditorContextMenu及其自己的菜单项,嵌套类{{1 }}。两者都来自EditorMenuItemContextMenu,分别来自。所以,如果它们是我设计的类的子类,那么为什么我的风格也不适用于它们呢?

我唯一能做的就是复制

的定义
MenuItem

从PresentationFramework.Aero的资源到我的样式文件。但这非常清楚地使我的菜单看起来像Windows 7,在Windows 8或10(或XP)上可能不会出现这种情况。但重新定义这种风格的关键可能会影响<ControlTemplate x:Key="{ComponentResourceKey TypeInTargetAssembly={x:Type MenuItem}, ResourceId=SubmenuItemTemplateKey}" TargetType="{x:Type MenuItem}"> 的外观。为什么呢?

如果EditorMenuItem没有自己的风格(我找不到它),为什么它不使用我为基类提供的任何风格?它如何知道使用我的样式,但只有默认的样式被替换并且不能用于其他每个上下文菜单?

这是XAML代码,存储在MenuStyles.xaml中,并包含在App.xaml的EditorMenuItem中。

ResourceDictionary

1 个答案:

答案 0 :(得分:2)

你的问题在于没有清楚地理解WPF中的样式如何工作。有两种类型的处理方式不同。

第一种是主题风格。每个FrameworkElementFrameworkContentElement在初始化时使用Style属性解析其自己的DefaultStyleKey。具有主题资源的资源字典的位置由ThemeInfoAttribute指定。

第二种类型是非主题风格。可以通过指定元素的Style属性来显式设置此样式。或者它也可以在初始化时隐式解决。非主题样式的Setter优先于主题样式的Setter

当您通过将非主题Style添加到应用程序的ResourceDictionary或没有键的元素时创建非主题Style时,它将隐式使用,并且仅使用目标类型的实例而不显式设置FrameworkElement.GetRawValue属性将受到影响,而不是派生类型。此行为在internal void GetRawValue(DependencyProperty dp, PropertyMetadata metadata, ref EffectiveValueEntry entry) { // ... if (dp != StyleProperty) { if (StyleHelper.GetValueFromStyleOrTemplate(new FrameworkObject(this, null), dp, ref entry)) { return; } } else { object source; object implicitValue = FrameworkElement.FindImplicitStyleResource(this, this.GetType(), out source); if (implicitValue != DependencyProperty.UnsetValue) { // This style has been fetched from resources HasImplicitStyleFromResources = true; entry.BaseValueSourceInternal = BaseValueSourceInternal.ImplicitReference; entry.Value = implicitValue; return; } } // ... } 方法(line 1887)中定义:

Style

因此,MenuItem未应用Style,因为它仅适用于Style课程,因为它不是主题TextBox。您有两种方法可以更改ContextMenu StyleTextBox项,但两者都有缺点。

第一种方法是为所有ContextMenu添加MenuItems并在其中设置<Style TargetType="{x:Type TextBox}"> <Setter Property="ContextMenu"> <Setter.Value> <ContextMenu> <MenuItem Command="ApplicationCommands.Copy" /> <MenuItem Command="ApplicationCommands.Cut" /> <MenuItem Command="ApplicationCommands.Paste" /> </ContextMenu> </Setter.Value> </Setter> </Style> 。但如果分别使用Text Services Framework和拼写检查,您将失去重新转换和拼写Style

TextEditorContextMenu.EditorMenuItem

第二种方法是在启动时使用反射为// Inside the Application.OnStartup method Style menuItemStyle = TryFindResource(typeof(MenuItem)) as Style; if (menuItemStyle != null) { Assembly menuItemAssembly = typeof(MenuItem).Assembly; Type editorMenuType = menuItemAssembly.GetType("System.Windows.Documents.TextEditorContextMenu+EditorMenuItem", false); if (editorMenuType != null) { Resources.Add(editorMenuType, menuItemStyle); } Type reconversionMenuType = menuItemAssembly.GetType("System.Windows.Documents.TextEditorContextMenu+ReconversionMenuItem", false); if (reconversionMenuType != null) { Resources.Add(reconversionMenuType, menuItemStyle); } } 类创建yum clean all。但是,只有在使用拼写检查和文本服务框架时才应使用此方法。

RUN yum -y install http://rpms.famillecollet.com/enterprise/remi-release-7.rpm && \
    yum -y install php-fpm php-mysqlnd php-mbstring php-intl php-amqp php-redis php-opcache --enablerepo remi,remi-php56 && \
    groupadd -g 1000 nginx && \
    useradd -u 1000 -g 1000 nginx && \
    yum clean all