修改屏幕DPI,会触发控件的Unloaded/Loaded

现象/重现案例

这里简单介绍下,修改屏幕DPI,触发Unloaded/Loaded的神奇案例

1. 我们新建一个窗口,添加一个UserControl1,然后在UserControl1中添加UserControl2

 <Window x:Class="WPFUnloadedTriggerTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WPFUnloadedTriggerTest"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<local:UserControl1></local:UserControl1>
</Window>
------------------------------我是分隔线-----------------------------------
<UserControl x:Class="WPFUnloadedTriggerTest.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WPFUnloadedTriggerTest"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<local:UserControl2></local:UserControl2>
</UserControl>

2. 显示窗口后,修改DPI比例

3. 设置完后,会触发Unloaded/Loaded重新加载

Unloaded的触发顺序是UserControl1-->UserControl2,Window并不会触发Unloaded事件!

是不是诡异?我们继续。。。

4. Window我们添加一个ControlTemplate模块

     <Window.Template>
<ControlTemplate TargetType="Window">
<Border>
<AdornerDecorator>
<ContentPresenter />
</AdornerDecorator>
</Border>
</ControlTemplate>
</Window.Template>

再重复2、3步骤,Unloaded的触发顺序变了:

触发UserControl2的Unloaded,Window、UserControl1并不会触发Unloaded事件!

问题分析

第2步骤中修改DPI后,Unloaded事件不一定触发。如何必现呢?

将窗口靠近到任务栏上方,再修改文本比例。

我们查看调用堆栈,貌似是系统给窗口发送消息然后调用BroadcastUnloadedEvent事件,触发Unload

所以应该是修改DPI,窗口宽高超出了当前屏幕尺寸范围,系统对UserControl的视觉树进行重新加载布局。

至于窗口没有触发Unloaded、以及在窗口添加以上模块后下一级子控件也没有触发Unloaded事件的原因,暂不了解

而对WPF-Unloaded/Loaded的已知情况如下:

  • FrameworkElement, 第一次加载显示时,会触发Loaded。元素被释放时,会触发Unloaded。窗口Show/Close时,视觉树变化都会触发加载事件
  • MenuItem, 在FrameworkElement基础上,每次和隐藏MenuItem时,会额外触发Load/Unloaded
  • TabControl,当你选中一个tabItem时会触发Loaded,当你取消选中一个tabItem时会触发Unloaded,所以切换Tab时必定有一个Loaded一个Unloaded。
  • Expander,每次被Expanded扩展时会引发Loaded,但当隐藏时不会引发Unloaded。

以上问题的解决方案?暂时没有解决方案,只有规避措施,不要过于依赖于Unload/Loaded,而且使用了Unload/Loaded时也要添加注销机制,防止重入

我在github提了个issue:After Modified screen dpi,Unloaded/Loaded is trigged unexpectedly

WPF 修改屏幕DPI,会触发控件重新加载Unload/Load的更多相关文章

  1. 重新想象 Windows 8.1 Store Apps (81) - 控件增强: 加载本地 html, 智能替换 html 中的 url 引用, 通过 Share Contract 分享 WebView 中的内容, 为 WebView 截图

    原文:重新想象 Windows 8.1 Store Apps (81) - 控件增强: 加载本地 html, 智能替换 html 中的 url 引用, 通过 Share Contract 分享 Web ...

  2. Delphi7 第三方控件1stClass4000的TfcImageBtn按钮控件动态加载jpg图片例子

    Delphi7 第三方控件1stClass4000的TfcImageBtn按钮控件动态加载jpg图片例子 procedure TForm1.Button1Click(Sender: TObject); ...

  3. easyui控件的加载顺序

    使用easyui做布局时,会模仿窗口程序界面,做出一些较复杂的布局.按由外层到内层的顺序: (最外层)panel->tabs->tabs1 ->tabs2->layout-&g ...

  4. 使用DevExpress.XtraTabbedMdi.XtraTabbedMdiManager控件来加载MDI窗体

    使用DevExpress.XtraTabbedMdi.XtraTabbedMdiManager控件来加载MDI窗体     [csharp] view plaincopyprint? <SPAN ...

  5. 在WinForm应用程序中,使用选项卡控件来加载不同的Form界面!

    TabPage tp=new TabPage(); your选项卡控件.Controls.Add(tp); From1 frm=new Form1(); frm.TopLevel = false; f ...

  6. Asp.net 的DropDownList 控件动态加载

    在做连接数据库表,在页面上用DropDownList 下拉框查询某条数据时,因为数据库里的数据,随时都有可能增加或减少,而下拉框关联的某个字段的值并不一定是固定的. 表信息: CREATE TABLE ...

  7. 【高德地图API】Pivot控件中加载地图并禁止Pivot手势

    如题,解决方案,参考[Windows phone应用开发[20]-禁止Pivot手势]http://www.cnblogs.com/chenkai/p/3408658.html. xaml代码清单   ...

  8. WPF中不规则窗体与WindowsFormsHost控件的兼容问题完美解决方案

    首先先得瑟一下,有关WPF中不规则窗体与WindowsFormsHost控件不兼容的问题,网上给出的解决方案不能满足所有的情况,是有特定条件的,比如  WPF中不规则窗体与WebBrowser控件的兼 ...

  9. Jquery如何序列化form表单数据为JSON对象 C# ADO.NET中设置Like模糊查询的参数 从客户端出现小于等于公式符号引发检测到有潜在危险的Request.Form 值 jquery调用iframe里面的方法 Js根据Ip地址自动判断是哪个城市 【我们一起写框架】MVVM的WPF框架(三)—数据控件 设计模式之简单工厂模式(C#语言描述)

    jquery提供的serialize方法能够实现. $("#searchForm").serialize();但是,观察输出的信息,发现serialize()方法做的是将表单中的数 ...

随机推荐

  1. 05 python学习笔记-常用内置函数(五)

    1.sorted() 函数对所有可迭代的对象进行排序(默认升序)操作 sort 与 sorted 区别: sort 是应用在 list 上的方法,sorted 可以对所有可迭代的对象进行排序操作. l ...

  2. zepto源码分析·ajax模块

    准备知识 在看ajax实现的时候,如果对ajax技术知识不是很懂的话,可以参看下ajax基础,以便读分析时不会那么迷糊 全局ajax事件 默认$.ajaxSettings设置中的global为true ...

  3. 你编写的Java代码是咋跑起来的?

    如果你是一名 Java 开发人员,你肯定指定 Java 代码有很多种不同的运行方式.比如说可以在开发工具(IDEA.Eclipse等)中运行,可以双击执行 jar 文件运行,也可以在命令行中运行,甚至 ...

  4. 2018.8.8 python 初识函数

    主要内容: 1.函数定义 2.函数名,函数体以及函数的调用 3.函数的返回值 4.函数的参数 一.函数的定义 函数:对代码块和功能的封装和定义. 二.函数名.函数体及函数的调用 我们使用def关键字来 ...

  5. centos7 搭建ftp 并配置用户目录

    1.如果是阿里云服务器,登录控制后台,配置规则,开启21端口 (sftp是加密文件传输使用的22端口,我们这几是搭建ftp服务器) 2.安装配置vsftp服务器 一.配置防火墙,开启FTP服务器需要的 ...

  6. 运营的Python指南 - Python 操作Excel

    这是一份写给运营人员的Python指南.本文主要讲述如何使用Python操作Excel.完成Excel的创建,查询和修改操作. 相关代码请参考 https://github.com/RustFishe ...

  7. Spring Boot2 系列教程(二十)Spring Boot 整合JdbcTemplate 多数据源

    多数据源配置也算是一个常见的开发需求,Spring 和 SpringBoot 中,对此都有相应的解决方案,不过一般来说,如果有多数据源的需求,我还是建议首选分布式数据库中间件 MyCat 去解决相关问 ...

  8. 等距结点下的Newton插值多项式系数计算(向前差分)

    插值多项式的牛顿法 1.为何需要牛顿法? ​ 使用Lagrange插值法不具备继承性.当求好经过\(({x_0},{y_0})-({x_n},{y_n})\)共n+1个点的插值曲线时候,如果再增加一个 ...

  9. 「2019.8.11 考试」一套把OI写的很诗意的题

    这次写的更惨了,T2暴力再次挂掉了. 先写了T1的75暴力,然后写了T2的70分暴力(挂成了25),T3啥也不会骗了12分.T3看完题一点思路没有,心态爆炸了,一直在观察数据,忽略的思考的重要性,以至 ...

  10. css3自定义移动端滚动条

    css3自定义移动端滚动条<pre>/*定义滚动条宽 高度是根据内容设置的高度决定的*/::-webkit-scrollbar{ width: 5px;} /*定义滚动条轨道 内阴影+圆角 ...