【wpf】视觉树上找元素的注意事项

news2024/11/15 15:41:22

前言

我们通过 VisualTreeHelper类 可以在视觉树上找元素,下面提供几个封装好的方法:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;
using System.Windows;

namespace VisionCore.Tools
{
    public class FindVisualTree
    {
        /// <summary>
        /// 根据类型查找子元素
        /// 调用形式:  List<StackPanel> initToolBarWeChatUserSp = GetChildObjects<StackPanel>(name, typeof(StackPanel));
        /// </summary>
        /// <typeparam name="T">查找类型</typeparam>
        /// <param name="obj">查询对象</param>
        /// <returns></returns>
        static public List<T> GetChildObjects<T>(DependencyObject obj) where T : FrameworkElement
        {
            DependencyObject child = null;
            List<T> childList = new List<T>();

            Type typename = typeof(T);

            for (int i = 0; i <= VisualTreeHelper.GetChildrenCount(obj) - 1; i++)
            {
                child = VisualTreeHelper.GetChild(obj, i);

                if (child is T && (((T)child).GetType() == typename))
                {
                    childList.Add((T)child);
                }
                childList.AddRange(GetChildObjects<T>(child));
            }
            return childList;
        }


        static public T GetChildObjectFirst<T>(DependencyObject obj) where T : FrameworkElement
        {
            List<T> childList = new List<T>();

            childList = GetChildObjects<T>(obj);
            if (childList.Count > 0)
            {
                return childList[0];
            }
            else
            {
                return null;
            }

        }



        /// <summary>
        /// 获取父可视对象中第一个指定类型的子可视对象
        /// </summary>
        /// <typeparam name="T">可视对象类型</typeparam>
        /// <param name="parent">父可视对象</param>
        /// <returns>第一个指定类型的子可视对象</returns>
        public static T GetVisualChild<T>(Visual parent) where T : Visual
        {
            T child = default(T);
            int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
            for (int i = 0; i < numVisuals; i++)
            {
                Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
                child = v as T;
                if (child == null)
                {
                    child = GetVisualChild<T>(v);
                }
                if (child != null)
                {
                    break;
                }
            }
            return child;
        }



        static public T GetChildObjectWithName<T>(DependencyObject obj, string name) where T : FrameworkElement
        {
            List<T> childList = new List<T>();

            childList = GetChildObjects<T>(obj);

            foreach (var item in childList)
            {
                if (item.Name == name)
                {
                    return item;
                }
            }
            return null;
        }
    }
}

以上函数,使用了递归的方式,可以一层层的查找。

问题出现

但是,我发现有时候,这种方式会失效!

我使用 VisualTreeHelper 类,在 TabControl 控件中 想在 TabItem 寻找一个子控件。但是我发现只能找到当前显示的TabItem中的控件,没显示的找不到。

我尝试了各种办法,比如 TabControl 加载事件中获取,或者 TabItem 的加载事件中获取,都不行。给我的感觉就是只有当前界面显示了,再去通过VisualTreeHelper找,才能找到。

于是,我在 TabControl 的页面切换的事件中去找:

 但是如果直接找,还是找不到,需要让主线程先运行一会再找。

这里的 Application.Current.Dispatcher.BeginInvoke 是为了解决跨线程的问题。

其实这个500ms的延时可以不用(但是必须保证这种方式的写法,也就是让主线程先执行下)。

那最终的写法如下:

SelectionChangedCmd = new DelegateCommand<RoutedEventArgs>((e) => {
	DependencyObject? obj = e.OriginalSource as DependencyObject;
	if (hSmartTemp == null)
	{
		var t = Task.Factory.StartNew(() =>
		{
			Application.Current.Dispatcher.BeginInvoke(new Action(async () =>
			{
				Console.WriteLine("Start");
				await Task.Delay(500);//异步等一等,让主线程先执行一会!
				hSmartTemp = FindVisualTree.GetChildObjectFirst<HSmartWindowControlWPF>(obj);
			}));

		});
		t.Wait();
	}                
});

对应的前台代码:

 

小结

        给我的感觉就是只有当前界面显示了,再去通过VisualTreeHelper找,才能找到。

结语

        欢迎评论区参与讨论!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/564425.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

分析| Flutter 3.10版本有哪些变化?

Flutter是Google推出的一款用于构建高性能、高保真度移动应用程序、Web和桌面应用程序的开源UI工具包。Flutter使用自己的渲染引擎绘制UI&#xff0c;为用户提供更快的性能和更好的体验。Flutter还提供了丰富的构建工具、库和插件&#xff0c;使开发人员能够更快地构建应用程序…

从浅入深理解序列化和反序列化

文章目录 什么是java序列化什么情况需要使用 Java 序列化为什么要序列化序列化和反序列化过程如下RPC 框架为什么需要序列化序列化用途序列化机制可以让对象地保存到硬盘上&#xff0c;减轻内存压力的同时&#xff0c;也起了持久化的作用序列化机制让Java对象可以在网络传输 实…

LINUX 提权 脏牛CVE-2016-5195

这里写复现过程&#xff0c;不写原理 Linux内核 > 2.6.22&#xff08;2007年发行&#xff0c;到2016年10月18日才修复&#xff09; 靶场环境是vluhub上的。网卡自己配置好 nmap扫一下 80端口开的&#xff0c;上去 52.136 再扫 1898开放 访问开干 是个cms msf上线找这…

【VictoriaMetrics】VictoriaMetrics单机版批量和单条数据写入(opentsdb格式)

VictoriaMetrics单机版支持以opentsdb格式的数据写入包含linux形式和postman形式,写入支持单条数据写入以及多条数据写入,下面操作演示下如何使用 1、首先需要启动VictoriaMetrics单机版服务 注意,如果支持opentsdb协议需要在启动单机版VictoriaMetrics的时候加上opentsdbH…

一、尚医通微信登录

文章目录 一、登录需求1、登录需求 二、微信登录1、OAuth21.1OAuth2解决什么问题1.1.1 开放系统间授权1.1.2图例1.1.3方式一&#xff1a;用户名密码复制1.1.4方式二&#xff1a;通用开发者key1.1.5方式三&#xff1a;颁发令牌 1.2 OAuth2最简向导1.2.1 OAuth主要角色1.2.2最简向…

就业内推 | 国企招运维、网安,五险一金全额缴,最高15k

01 北京安信创业信息科技发展有限公司 &#x1f537;招聘岗位&#xff1a;网络运维岗 &#x1f537;职责描述&#xff1a; 1、负责北区数据中心、总部数据中心、部本部、21家在京直属事业单位内网网络系统的日常运行维护工作。 2、负责网络故障的应急处置。 3、负责网络系统…

决策树及决策树的划分依据(ID3、C4.5、CART)

一、决策树是什么&#xff1f; 决策树是一种基于树状结构的机器学习算法&#xff0c;用于解决分类和回归问题。它是一种自上而下的递归分割方法&#xff0c;通过对特征空间的递归划分来构建一个树形模型&#xff0c;用于进行预测和决策。在决策树中&#xff0c;每个内部节点表…

Redis概述

前言 为什么要使用Redis? ​ 如果熟悉JVM底层的话&#xff0c;就能了解Java程序的运行大多数都是基于对内存的操作&#xff0c;读取、并更、清理&#xff0c;并同时保证数据的可靠性。即使是数据库&#xff0c;例如MySQL几乎都是基于对缓冲区的操作&#xff0c;只是通过后台…

(常见)数据模型

文章目录 数据模型概述一、数据模型概要1.模型、建模与抽象2.数据模型3.两类数据模型 二、数据库模型的组成要素1.数据结构2.数据操作3.数据的完整性约束 三、概念模型1.概要2.基本概念3.概念模型的表示方法 常用数据模型一、层次模型1.简介2.数据结构3.数据操纵与完整性约束4.…

二叉搜索树中第K小的元素

给定一个二叉搜索树的根节点 root &#xff0c;和一个整数 k &#xff0c;请你设计一个算法查找其中第 k 个最小元素&#xff08;从 1 开始计数&#xff09;。 示例 1&#xff1a; 输入&#xff1a;root [3,1,4,null,2], k 1 输出&#xff1a;1 示例 2&#xff1a; 输入&am…

List、Set、Map的区别?

List 是一个有序集合&#xff0c;里面可以存储重复的元素Set 是一个不能存储相同元素的集合Map 是一个通过键值对的方式存储元素的&#xff0c;键不能重复 Java 容器分为Collection 和Map 两大类&#xff0c;Collection 集合的子接口有Set、List、Queue 三种子接口。其中&#…

CSDN MD编辑器跳转方法及字体格式

一、点击关键语句跳转指定位置 在CSDN写文章的时候&#xff0c;写的文章过长往往会让读者很难找到自己想看的部分&#xff0c;这时候有个 跳转到指定位置功能 就非常的便利。CSDN在MD编辑器上(富文本编辑器只有一种)就提供了两种跳转到指定位置的方法&#xff1a; 一、目录跳转…

HackTheBox-关卡Fawn

1. 连接靶场&#xff0c;打开FAWN实例场景&#xff0c;检查是否互通 TASK1 3 个字母的首字母缩写词 FTP 代表什么&#xff1f; 答案是&#xff1a;File Transfer Protocol TASK2 问题是&#xff1a;FTP服务通常监听哪个端口&#xff1f; FTP监听的TCP端口号为21,监听的数据端…

【自动化测试】selenium工具

文章目录 为什么要做自动化测试&#xff1f;为什么选用Selenium&#xff1f;Selenium的工作原理SeleniumJava环境搭建Selenium常用API浏览器参数配置定位元素操作测试对象时间等待信息打印对浏览器操作键盘与鼠标操作屏幕截图弹窗处理选择框的处理上传文件 JUnit单元测试注解参…

睡岗识别 TensorFlow

睡岗识别可以通过TensorFlowAI深度学习框架智能分析技术&#xff0c;睡岗识别识别出现场人员是否存在睡岗情况&#xff0c;及时发出预警&#xff0c;避免因操作人员的疏忽而导致的安全事故。TensorFlow 是一个开源的机器学习的框架&#xff0c;我们可以使用 TensorFlow 来快速地…

3年自动化测试这水平?我还不如去招应届生...

公司前段缺人&#xff0c;也面了不少测试&#xff0c;结果竟然没有一个合适的。一开始瞄准的就是中级的水准&#xff0c;也没指望来大牛&#xff0c;提供的薪资在10-20k&#xff0c;面试的人很多&#xff0c;但平均水平很让人失望。看简历很多都是3年工作经验&#xff0c;但面试…

【Python Seaborn】零基础也能轻松掌握的学习路线与参考资料

Python Seaborn是一个基于Python的可视化库&#xff0c;为Matplotlib库的扩展&#xff0c;提供了更加高级的数据可视化功能和丰富的统计图形。在学习Python数据科学和机器学习中&#xff0c;Seaborn有很好的数据可视化工具&#xff0c;也能够提供有帮助的统计图表来揭示数据之间…

实时频谱-2.5DPX

数字荧光显示 “数字荧光”一词源自包在阴极射线管(CRT)上的荧光&#xff0c;电视机、计算机监视器和其它测试设备显示器都使用阴极射线管。在电子束激活荧光时&#xff0c;它会发出荧光&#xff0c;照亮电子流画出的路径。 尽管液晶显示器(LCD)之类的光栅扫描技术由于厚度和…

29 KVM管理系统资源-调整虚拟CPU绑定关系

文章目录 29 KVM管理系统资源-调整虚拟CPU绑定关系29.1 概述29.2 操作步骤 29 KVM管理系统资源-调整虚拟CPU绑定关系 29.1 概述 把虚拟机的vCPU绑定在物理CPU上&#xff0c;即vCPU只在绑定的物理CPU上调度&#xff0c;在特定场景下达到提升虚拟机性能的目的。比如在NUMA系统中…

基于孪生网络的目标跟踪

一、目标跟踪 目标跟踪是计算机视觉领域研究的一个热点问题&#xff0c;其利用视频或图像序列的上下文信息&#xff0c;对目标的外观和运动信息进行建模&#xff0c;从而对目标运动状态进行预测并标定目标的位置。具体而言&#xff0c;视觉目标&#xff08;单目标&#xff09;…