本文记录将 WPF 控件放入到 UserControl 里,如果此 UserControl 没有被设置 Visibility 为可见过,那么放在此 UserControl 内的控件将获取不到 HwndSource 内容

如果对某个 Visual 使用 PresentationSource.FromVisual 方法获取 HwndSource 内容,获取到的返回是空值。那么可能的原因是这个 Visual 所在的容器,或者说所在的容器的所在的容器,只要在此控件的视觉树上向上寻找,能寻找到 UserControl 控件,或者是继承 UserControl 控件的控件。那么可能的原因是此 UserControl 控件,从未被设置 Visibility 为 Visible 过的原因导致的

本文接下来将使用 Demo 演示最短复现方法,告诉大家为什么从 PresentationSource.FromVisual 方法获取 null 空值的原因,和什么时候调用 PresentationSource.FromVisual 返回 null 空值

对于 WPF 里定义的几乎所有的容器控件,如 Grid 等,即使此容器控件被设置为 Visibility="Collapsed" 也能让里层的控件,可以拿到 HwndSource 内容。例如以下的 XAML 逻辑

    <Grid x:Name="RootGrid">
<Grid Visibility="Collapsed">
<TextBox x:Name="TextBox1"></TextBox>
</Grid>
<UserControl x:Name="UserControl" Visibility="Collapsed">
<TextBox x:Name="TextBox2"></TextBox>
</UserControl>
</Grid>

非常相同,将一个 TextBox 分别放入到 Grid 和 UserControl 里面,将 Grid 和 UserControl 设置为 Visibility="Collapsed" 不可见

在 Loaded 事件里面,分别从 TextBox1 和 TextBox2 获取 HwndSource 内容,代码如下

        public MainWindow()
{
InitializeComponent(); Loaded += MainWindow_Loaded;
} private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
var hwndSource1 = (HwndSource) PresentationSource.FromVisual(TextBox1); // not null
var hwndSource2 = (HwndSource) PresentationSource.FromVisual(TextBox2); // null if (hwndSource1 is null)
{
throw new ArgumentNullException(nameof(hwndSource1));
} if (hwndSource2 is null)
{
throw new ArgumentNullException(nameof(hwndSource2));
}
}

执行代码,可以看到,可以从放入到 Grid 里的 TextBox1 拿到 HwndSource 内容。从放入到 UserControl 里面的 TextBox1 拿到空

有趣的是,如果从 UserControl 拿到 HwndSource 内容,是可以拿到内容的。如果将此 UserControl 的 Visibility 先设置为 Visible 然后再设置为 Collapsed 的值,那么在 UserControl 里面的控件,依然可以拿到 HwndSource 内容。如以下代码

        <UserControl x:Name="UserControl" Visibility="Visible">
<TextBox x:Name="TextBox2"></TextBox>
</UserControl>

在后台代码,先设置 UserControl 的 Visibility 属性,再等待一秒,获取 HwndSource 内容,如以下代码

        private async void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
UserControl.Visibility = Visibility.Collapsed; await Task.Delay(1000); var hwndSource2 = (HwndSource) PresentationSource.FromVisual(TextBox2); // 可以拿到
}

可以看到,只要 UserControl 设置过 Visibility 为 Visible 即可让放入到 UserControl 的控件拿到 HwndSource 内容

因此,如果发现从某个 Visual 上,尝试获取 HwndSource 内容失败,可以看看此控件所在的视觉树上是否被放入到 UserControl 里面,同时这个 UserControl 还没有被设置 Visibility 为 Visible 过

本文所有代码放在githubgitee 欢迎访问

可以通过如下方式获取本文的源代码,先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码

git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin 013b01d618e655c8f89e088e0e5b02f7c1616233

以上使用的是 gitee 的源,如果 gitee 不能访问,请替换为 github 的源

git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git

获取代码之后,进入 FurwihobawNawkanenea 文件夹

Any way to get an HWND of a UserControl? - Visual Studio 2008 - Windows Tech

Any way to get an HWND of a UserControl?


更新:

不是只有 UserControl 有此问题,而是所有需要 Template 的控件,都存在此问题。例如 Button 按钮也一样,如以下代码,将 TextBox2 放入到 Button 里面,其行为和放入到 UserControl 是相同的

        <Button x:Name="Button" Visibility="Collapsed">
<TextBox x:Name="TextBox2"></TextBox>
</Button>

更改 MainWindow_Loaded 函数为以下代码

        private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
var hwndSource1 = (HwndSource) PresentationSource.FromVisual(TextBox1); // not null
var hwndSource2 = (HwndSource) PresentationSource.FromVisual(TextBox2); // null
var logicalParent = LogicalTreeHelper.GetParent(TextBox2); // Button
var visualParent = VisualTreeHelper.GetParent(TextBox2); // null
}

可以看到从 TextBox2 只能存在逻辑树上,没有建立过视觉树关系。原因是 Button 或 UserControl 控件,不会立即调用 ApplyTemplate 应用资源创建里层控件,只有在必要的时候才进行初始化。因此没有被初始化的 TextBox2 自然就找不到任何可用的 HwndSource 内容

更新的代码也放在githubgitee 欢迎访问

可以通过如下方式获取本文的源代码,先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码

git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin b2dafcd7f3b86efd6283dd8bf6a37cfb85765aa9

以上使用的是 gitee 的源,如果 gitee 不能访问,请替换为 github 的源

git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git

获取代码之后,进入 FurwihobawNawkanenea 文件夹

WPF 将控件放入到 UserControl 里获取 HwndSource 为空的情况的更多相关文章

  1. ios-将代码创建的视图控件放入拖拽控件的下面

    如图所示 图片是拖拽上去的imageView,橘黄色控件是在代码中创建的添加上去的,此时黄色view在imageView 上方 调用方法bringSubviewToFront:试图将imageView ...

  2. WPF 用户控件的自定义依赖属性在 MVVM 模式下的使用备忘

    依赖属性相当于扩充了 WPF 标签的原有属性列表,并可以使用 WPF 的绑定功能,可谓是十分方便的:用户控件则相当于代码重用的一种方式:以上几点分开来还是比较好理解的,不过要用到MVVM 模式中,还是 ...

  3. 创建 WPF 工具箱控件

    创建 WPF 工具箱控件 WPF (Windows Presentation Framework) 工具箱控件模板允许您创建 WPF 控件,会自动添加到 工具箱 安装扩展的安装. 本主题演示如何使用模 ...

  4. WPF 分页控件 WPF 多线程 BackgroundWorker

    WPF 分页控件 WPF 多线程 BackgroundWorker 大家好,好久没有发表一篇像样的博客了,最近的开发实在头疼,很多东西无从下口,需求没完没了,更要命的是公司的开发从来不走正规流程啊, ...

  5. 创建WPF用户控件

    wpf用户自定义控件和winform创建方法类似,这里先纠正一个误区,就是有很多人也是添加,然后新建,然后是新建用户控件库,但是为什么编译好生成后Debug目录下还是只有exe文件而没有dll文件呢? ...

  6. WPF滑块控件(Slider)的自定义样式

    前言 每次开发滑块控件的样式都要花很久去读样式代码,感觉有点记不牢,所以特此备忘. 自定义滑块样式 首先创建项目,添加Slider控件. 然后获取Slider的Window样式,如下图操作. 然后弹出 ...

  7. C# WPF开源控件库:MahApps.Metro

    其实站长很久之前就知道这个开源WPF控件库了,只是一直欣赏不了这种风格,但也star了该项目.每次浏览该仓库时,发现star越来越多,也看到很多网友对它的褒奖,所以今天就向大家推荐这款WPF控件库. ...

  8. WPF 截图控件之绘制方框与椭圆(四) 「仿微信」

    前言 接着上周写的截图控件继续更新 绘制方框与椭圆. 1.WPF实现截屏「仿微信」 2.WPF 实现截屏控件之移动(二)「仿微信」 3.WPF 截图控件之伸缩(三) 「仿微信」 正文 有开发者在B站反 ...

  9. WPF Popup 控件导致被遮挡内容不刷新的原因

    WPF Popup 控件导致被遮挡内容不刷新的原因 周银辉 今天在写一个WPF控件时用到了Popup控件,很郁闷的情况是:当popup关闭时,原来被popup挡住的界面部分不刷新,非要手动刷新一下(比 ...

  10. wpf打印控件 实现分页打印控件功能

    因为 要实现打印 wpf  listbox控件  数据特别多 要打印在 几张纸上    找了几天 都没有找到相关的例子 现在 解决了 在这里和大家分享一下 public void print(Fram ...

随机推荐

  1. python基础九(模块和包)

    一 模块介绍 1.什么是模块? 模块就是一系列功能的集合体,分为三大类 I:内置的模块(python解释器内置) II:第三方的模块 III:自定义的模块 一个python文件本身就是一个模块,文件名 ...

  2. uniapp热更新和整包更新思路

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 我们知道,在打包Android App之前,我们需要先通过HX生成打包资源.如果是通过cli创建的项目,则通过以下命令生成打包资源: ya ...

  3. 大模型时代的PDF解析工具

    去年(2023年)是大模型爆发元年.但是大模型具有两个缺点:缺失私有领域知识和幻觉.缺失私有领域知识是指大模型训练时并没有企业私有数据/知识,所以无法正确回答相关问题.并且在这种情况下,大模型会一本正 ...

  4. Linux下配置node环境与failed to create symbolic link ‘/usr/bin/utserver’: File exists跟Error: Cannot find module '/root/node-v10.16.3-linux-x64/install'解决方法

    NodeJS下载地址(官网) https://nodejs.org/en/download/ 下载下来后是个tar,xz压缩包 通过xftp将压缩包上传到Linux服务器上 如我放在root目录下 使 ...

  5. C++获取任务管理器信息,封装成DLL,C#调用例子

    C++代码 pch.h // pch.h: 这是预编译标头文件. // 下方列出的文件仅编译一次,提高了将来生成的生成性能. // 这还将影响 IntelliSense 性能,包括代码完成和许多代码浏 ...

  6. 添加AvalonEdit控件到WinForm

    public frmTest() { InitializeComponent(); ElementHost host = new ElementHost(); host.Size = new Size ...

  7. ChatTuGraph:通过大模型“与图对话”

    使用SQL(Structured Query Language)对数据库/数据仓库进行查询分析操作,几乎成了研发工程师和数据分析师的"家常便饭",然而要写出高效.清晰.优雅的SQL ...

  8. d3d12龙书阅读----绘制几何体(上)

    d3d12龙书阅读----绘制几何体(上) 本节主要介绍了构建一个简单的彩色立方体所需流程与重要的api 下面主要结合立方体代码分析本节相关知识 顶点 输入装配器阶段的输入 首先,我们需要定义立方体的 ...

  9. Spring Cloud相关组件说明

    1.Spring Cloud版本 现有Spring Cloud有两代实现,分为Spring Cloud Netflix和Spring Cloud Alibaba,由于SpringCloud Netfl ...

  10. DIY 3 种分库分表分片算法,自己写的轮子才吊!

    大家好,我是小富- 前言 本文是<ShardingSphere5.x分库分表原理与实战>系列的第六篇,书接上文实现三种自定义分片算法.通过自定义算法,可以根据特定业务需求定制分片策略,以满 ...