WPF 已知问题 Separator 无法应用 ContextMenu 定义的默认样式
本文记录一个 WPF 已知问题,在 ContextMenu 的 Resources 里定义 Separator 的默认样式,在 ContextMenu 里面的 Separator 将应用不上,或者说不会找到此默认的样式。需要明确给 Style 一个 Key 且在 Separator 写明此 Key 才能应用上
如下面的例子,在 ContextMenu 的 Resources 资源里面定义了 Separator 的默认样式
<ContextMenu>
<ContextMenu.Resources>
<Style TargetType="Separator">
<Setter Property="Margin" Value="10,10,10,10"></Setter>
</Style>
</ContextMenu.Resources>
</ContextMenu>
接着在 ContextMenu 里面存放一个 Separator 元素,可以看到此 Separator 元素没有使用或者说找到定义的样式,视觉上就是 Margin 没有生效
<ContextMenu>
<ContextMenu.Resources>
<Style TargetType="Separator">
<Setter Property="Margin" Value="10,10,10,10"></Setter>
</Style>
</ContextMenu.Resources>
<Separator></Separator>
</ContextMenu>
而如果给 Separator 的 Style 加上 Key 且在 Separator 写明了此 Key 那么将可以成功应用上,如下面代码
<ContextMenu>
<ContextMenu.Resources>
<Style x:Key="SeparatorStyle" TargetType="Separator">
<Setter Property="Margin" Value="10,10,10,10"></Setter>
</Style>
</ContextMenu.Resources>
<Separator Style="{StaticResource SeparatorStyle}"></Separator>
</ContextMenu>
此问题是在 WPF 代码里面写了特殊判断逻辑,预计是有我没有理解的坑才如此做。感谢 少珺 工具人帮我找到了在 WPF 框架里面的问题
为了方便说明问题,我将给出可以运行的测试代码,此测试代码可以在本文末尾找到项目的下载
新建一个 WPF 项目,编辑主窗口,添加以下代码
<Grid Background="White" MouseDown="Grid_OnMouseDown">
<Grid.ContextMenu>
<ContextMenu>
<ContextMenu.Resources>
<Style TargetType="Separator">
<Setter Property="Margin" Value="10,10,10,10"></Setter>
</Style>
<Style x:Key="SeparatorStyle" TargetType="Separator">
<Setter Property="Margin" Value="10,10,10,10"></Setter>
</Style>
</ContextMenu.Resources>
<Menu>1</Menu>
<Menu>2</Menu>
<Menu>3</Menu>
<Separator></Separator>
<Menu>1</Menu>
<Menu>2</Menu>
<Menu>3</Menu>
<Separator Style="{StaticResource SeparatorStyle}"></Separator>
<Menu>1</Menu>
<Menu>2</Menu>
<Menu>3</Menu>
</ContextMenu>
</Grid.ContextMenu>
</Grid>
对应的后台代码如下
private void Grid_OnMouseDown(object sender, MouseButtonEventArgs e)
{
var grid = (Grid)sender;
grid.ContextMenu.IsOpen = true;
}
此时点击窗口内容,即可看到弹出了菜单
弹出的菜单的两条分割线的 Margin 是不相同的
根本原因是在 WPF 里面,对于在 Menu 里面的 Separator 采用的是如下逻辑,以下代码可以从 WPF 官方开源仓库 https://github.com/dotnet/wpf/blob/1aab9e3f42dbf550797bff97a32f2dbfb61a3198/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/MenuItem.cs#L1344-L1353 找到。我此问题报告给 WPF 官方,请看 https://github.com/dotnet/wpf/issues/7268
Separator separator = item as Separator;
if (separator != null)
{
bool hasModifiers;
BaseValueSourceInternal vs = separator.GetValueSource(StyleProperty, null, out hasModifiers);
if (vs <= BaseValueSourceInternal.ImplicitReference)
separator.SetResourceReference(StyleProperty, SeparatorStyleKey);
separator.DefaultStyleKey = SeparatorStyleKey;
}
从上面代码可以看到,判断如果样式是小于等于 ImplicitReference 优先级的,那就采用默认的 SeparatorStyleKey 作为样式属性。如果没有在代码里面明确给定资源的 Key 内容,那以上代码的 vs 就是 ImplicitReference 优先级,于是样式就被修改为默认的主题样式
这是在 WPF 里面特别给定的代码,也许是大佬们为了修复某个我理解不了的坑
可以通过如下方式获取本文的源代码,先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码
git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin b820847a1af20370de28a1e73e32df9561a98ecc
以上使用的是 gitee 的源,如果 gitee 不能访问,请替换为 github 的源。请在命令行继续输入以下代码
git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
git pull origin b820847a1af20370de28a1e73e32df9561a98ecc
获取代码之后,进入 HayhachujedaKikunayreefee 文件夹
更多 WPF 已知问题请参阅 博客导航
大佬 czdietrich 告诉我说,这是特意的。原因是 Separator 在很多个地方都会使用,如果在 Menu 里,也采用默认继承的关系,将会让 Separator 的样式打架。毕竟在 Menu 里面的,是期望比较特殊一些的。于是就限制了,如果是放在 Menu 里面,应该采用的是 MenuItem.SeparatorStyleKey
样式的才会作为默认的继承样式,如下面代码
<Window x:Class="TestContextMenuSeparatorStyle.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Window.Resources>
<Style x:Key="{x:Static MenuItem.SeparatorStyleKey}" TargetType="Separator">
<Setter Property="Background" Value="Tomato" />
</Style>
</Window.Resources>
<Grid Background="White">
<Grid.ContextMenu>
<ContextMenu>
<MenuItem Header="Item 1" />
<Separator />
<MenuItem Header="Item 2" />
</ContextMenu>
</Grid.ContextMenu>
</Grid>
</Window>
以上的代码也符合 WPF 的逻辑,详细请看 https://github.com/dotnet/wpf/issues/7268#issuecomment-1315303718
WPF 已知问题 Separator 无法应用 ContextMenu 定义的默认样式的更多相关文章
- WPF 左键单击弹出菜单 ContextMenu
原文:WPF 左键单击弹出菜单 ContextMenu WPF中的ContextMenu在XAML中可直接做出来,但是仅限于右键弹出菜单,如果需要添加左键弹出功能,只需要在事件中添加Click事件 X ...
- 风口之下,猪都能飞。当今中国股市牛市,真可谓“错过等七年”。 给你一个回顾历史的机会,已知一支股票连续n天的价格走势,以长度为n的整数数组表示,
转自:http://www.cnblogs.com/ranranblog/p/5845010.html 风口之下,猪都能飞.当今中国股市牛市,真可谓“错过等七年”. 给你一个回顾历史的机会,已知一支股 ...
- Delphi 查找标题已知的窗口句柄,遍历窗口控件句柄(转)
用我的方法来控制其他程序窗体上的窗口控件,必须先了解什么是 回调函数.我的理解是这样的: 回 调函数写出来不是自己的程序去调用的,反而是让其他的东西去调用,比如windows操作系统,比如其他的程序等 ...
- 对象布局已知时 C++ 对象指针的转换时地址调整
在我调试和研究 netscape 系浏览器插件开发时,注意到了这个问题.即,在对象布局已知(即对象之间具有继承关系)时,不同类型对象的指针进行转换(不管是隐式的从下向上转换,还是强制的从上到下转换)时 ...
- ARCgis已知线裁剪已知面
经常遇到需要在ArcGIS中,根据已知线图层(要素)切分已知面图层(要素).经过研究,利用topology拓扑菜单中的construct features可以实现.具体如下 现有用线图层A.面图层B, ...
- Java集合-5. (List)已知有一个Worker 类如下: 完成下面的要求 1) 创建一个List,在List 中增加三个工人,基本信息如下: 姓名 年龄 工资 zhang3 18 3000 li4 25 3500 wang5 22 3200 2) 在li4 之前插入一个工人,信息为:姓名:zhao6,年龄:24,工资3300 3) 删除wang5 的信息 4) 利用for 循
第六题 5. (List)已知有一个Worker 类如下: public class Worker { private int age; private String name; private do ...
- JAVA-集合作业-已知有十六支男子足球队参加2008 北京奥运会。写一个程序,把这16 支球队随机分为4 个组。采用List集合和随机数
第二题 已知有十六支男子足球队参加2008 北京奥运会.写一个程序,把这16 支球队随机分为4 个组.采用List集合和随机数 2008 北京奥运会男足参赛国家: 科特迪瓦,阿根廷,澳大利亚,塞尔维亚 ...
- WCF 已知类型和泛型解析程序 KnownType
数据协定继承 已知类型和泛型解析程序 Juval Lowy 下载代码示例 自首次发布以来,Windows Communication Foundation (WCF) 开发人员便必须处理数据协定继承方 ...
- 【编程题目】n 支队伍比赛,分别编号为 0,1,2。。。。n-1,已知它们之间的实力对比关系,
36.引用自网友:longzuo(运算)谷歌笔试: 19n 支队伍比赛,分别编号为 0,1,2....n-1,已知它们之间的实力对比关系,存储在一个二维数组 w[n][n]中,w[i][j] 的值代表 ...
- 已知树的前序、中序,求后序的java实现&已知树的后序、中序,求前序的java实现
public class Order { int findPosInInOrder(String str,String in,int position){ char c = str.charAt(po ...
随机推荐
- App磁盘沙盒工具实践
目录介绍 01.磁盘沙盒的概述 1.1 项目背景说明 1.2 沙盒作用 1.3 设计目标 02.Android存储概念 2.1 存储划分介绍 2.2 机身内部存储 2.3 机身外部存储 2.4 SD卡 ...
- 记录--JS-SDK页面打开提示realAuthUrl错误
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 测试环境好好地功能,上了生产,莫名其妙报错,开始以为是没有设置Js安全接口域名,结果让相应人员一查,已经设置了相应的域名,再看下公众号内的 ...
- IDEA 2019.3 plugins 插件搜索不出结果
proxy的url输入: http://127.0.0.1:1080 重启idea即可
- urllib+BeautifulSoup爬取并解析2345天气王历史天气数据
urllib+BeautifulSoup爬取并解析2345天气王历史天气数据 网址:东城历史天气查询_历史天气预报查询_2345天气预报 1.代码 import json import logging ...
- Java实现栈
package algorithm; import java.util.Arrays; import java.util.Iterator; /** @author Administrator @da ...
- 使用sbt对Scala程序进行打包并运行(Spark单机运行)
十.使用sbt对Scala程序进行打包并运行(Spark单机运行) 在./sparkapp 中新建文件 simple.sbt(vim ./sparkapp/simple.sbt),添加内容如下,声明该 ...
- 简直了,被“Java并发锁”问题追问到自闭...
故事 地铁上,小帅双目空洞地望着窗外...绝望,发自内心地感到绝望... 距离失业已经过去两个月了,这是小帅接到的第四次面试邀请."回去等通知吧...",简简单单的六个字,把小帅的 ...
- 6 CSS样式继承
6 样式继承 CSS的样式表继承指的是,特定的CSS属性向下传递到子孙元素.总的来说,一个HTML文档就是一个家族,然后html元素有两个子元素,相当于它的儿子,分别是head和body,然后body ...
- #线性dp#CF1110D Jongmah
题目 分析 考虑三个 \((i,i+1,i+2)\) 可以用 \((i,i,i)\) 和 \((i+1,i+1,i+1)\) 和 \((i+2,i+2,i+2)\) 代替, 所以这样的三元组本质上最多 ...
- Qt将程序最小角化到系统托盘
#include "test.h" #include "QPushButton" #include <QSystemTrayIcon> Test:: ...