• WPF 修改屏幕DPI,会触发控件重新加载Unload/Load


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

    现象/重现案例

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

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

     1 <Window x:Class="WPFUnloadedTriggerTest.MainWindow"
     2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     4         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
     5         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
     6         xmlns:local="clr-namespace:WPFUnloadedTriggerTest"
     7         mc:Ignorable="d"
     8         Title="MainWindow" Height="450" Width="800">
     9     <local:UserControl1></local:UserControl1>
    10 </Window>
    11 ------------------------------我是分隔线-----------------------------------
    12 <UserControl x:Class="WPFUnloadedTriggerTest.UserControl1"
    13              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    14              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    15              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    16              xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    17              xmlns:local="clr-namespace:WPFUnloadedTriggerTest"
    18              mc:Ignorable="d" 
    19              d:DesignHeight="450" d:DesignWidth="800">
    20     <local:UserControl2></local:UserControl2>
    21 </UserControl>
    View Code

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

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

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

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

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

    1     <Window.Template>
    2         <ControlTemplate TargetType="Window">
    3             <Border>
    4                 <AdornerDecorator>
    5                     <ContentPresenter />
    6                 </AdornerDecorator>
    7             </Border>
    8         </ControlTemplate>
    9     </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

  • 相关阅读:
    前端TypeScript编写的代码发布后怎么在浏览器中调试
    oracle中的执行计划
    oracle中的物化视图
    oracle中的exists 和not exists 用法
    Oracle中的索引详解
    Oracle中动态SQL拼接
    oracle 中sql优化的几种方法
    oracle中常用函数大全
    Oracle中游标的用法
    oracle中表分区的实现
  • 原文地址:https://www.cnblogs.com/kybs0/p/11943313.html
Copyright © 2020-2023  润新知