首页 > 其他分享 >WPF 将控件放入到 UserControl 里获取 HwndSource 为空的情况

WPF 将控件放入到 UserControl 里获取 HwndSource 为空的情况

时间:2022-09-29 08:23:30浏览次数:86  
标签:控件 git 代码 HwndSource Visibility 为空 UserControl

本文记录将 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 文件夹

标签:控件,git,代码,HwndSource,Visibility,为空,UserControl
From: https://www.cnblogs.com/lindexi/p/16733244.html

相关文章

  • GTK常用控件之图片控件( GtkImage )
    图片控件和标签的作用很类似,都是作为显示用的,只是图片控件显示的内容是图片。图片控件的创建:GtkWidget*gtk_image_new_from_file(constgchar*filename);filename:图片的......
  • qt的基本控件——列表控件
    列表控件1、listWIdgetQListWidget类列表框控件用来加载并显示多个列表项。QListWidgetItem类就是列表项类双击可以直接修改,添加多少行,也有属性可以修改字体颜色大小等......
  • SpringBoot中集成websocket后WebSocketServer中注入mapper为空
    场景SpringBoot整合WebSocket时调用service和mapper的方法:https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/114829426上面讲了在集成websocket后,调用mapper......
  • QT——qss对多个控件设置想同样式
    QToolButton#minBtn:hover,QToolButton#maxBtn:hover,QToolButton#restoreBtn:hover{background:rgb(255,255,255);}QToolButton#minBtn:pressed,QToolBut......
  • Qt Table Widget常用操作 添加复选框控件
    QtTableWidget常用操作一、鼠标悬浮在item上显示提示信息 1、在构造函数开启tableWidget控件的鼠标捕获功能//开启鼠标捕获功能(实现tablewidget的悬浮功能)......
  • SAP UI5 sap.ui.layout.Grid 控件宽度百分比的设置原理
    在Chrome开发者工具里使用SAPUI5扩展Inspector修改Grid控件的defaultSpan属性,会触发如下的代码:我们通过调用栈,可以发现SAPUI5Grid相关的框架代码调用,确......
  • SAP UI5 SimpleForm 控件实例的初始化调试
    simpleForm在XML视图里定义的editable属性:会触发SimpleForm.setEditable方法调用:同理,设置layout属性:这个layout是一个单独的实例:addAllToContent:把Si......
  • kivy入门初级控件(一)
    异步加载图片1fromkivy.appimportApp2fromkivy.uix.gridlayoutimportGridLayout3fromkivy.uix.imageimportImage,AsyncImage456classImageB......
  • Android activity控制RecyclerView中Adapter中的控件的显示和隐藏
    在实际开发中,我们通常会遇到,通过外面的控件去控制Adapter里面的checkbox按钮的显示或隐藏: 需求就是:点击批量选择显示checkbox,再次点击隐藏。 思路:在activity中,定义......
  • qt的基本控件——显示控件
    显示控件1、label作用就是用来显示一些文字的,或者用来贴图1、加载资源方式:右键项目-->addnew输入名字,就能得到一个qrc的一个包,然后在这个位置添加前缀/image表示图......