我曾经创建过一种样式来修复WPF中菜单项的错误外观。它主要是关于未对齐的菜单文本。它在左上角太远,没有使用适当的间距。
我发现它在窗口菜单中有效,但在TextBox
的上下文菜单中不,我现在测试了它。所以问题是,为什么这种风格不是从文本框中考虑上下文菜单?
更新:我发现TextBox
使用自己的菜单项类,私有嵌套类TextEditorContextMenu.EditorContextMenu
及其自己的菜单项,嵌套类{{1 }}。两者都来自EditorMenuItem
和ContextMenu
,分别来自。所以,如果它们是我设计的类的子类,那么为什么我的风格也不适用于它们呢?
我唯一能做的就是复制
的定义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
答案 0 :(得分:2)
你的问题在于没有清楚地理解WPF中的样式如何工作。有两种类型的处理方式不同。
第一种是主题风格。每个FrameworkElement
和FrameworkContentElement
在初始化时使用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
Style
中TextBox
项,但两者都有缺点。
第一种方法是为所有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