VisualTreeHelper不仅仅只是用来查看可视化树结构的
关于VisualTreeHelper这个类,大家应该都应该看到过,它是silverlight提供的一个帮助器类,通过它,以便您可以检查可视化树结构。今天,我们来通过对VisualTreeHelper的使用,来做一些比较有意思的事情,当然不止是查看可视化树的结构,是不是有点迫不及待了呢?其实,也没什么特别离谱,当然还是和可视化树有关啦。其实呢,今天,我们要使用VisualTreeHelper来通过对可视化树结构的遍历,“潜入”到控件的Template中去,通过对Template中元素的访问,来改变控件的一些不直接暴露在外的属性。
我不想ChildWindow每次都从屏幕中间弹出
最近,在做与ChildWindow相关的项目时,发现每次在调用它显示的时候,它都从屏幕中间弹出,但是有时候,我们需要它从特定的位置弹出,查看了下文档,发现并没有现成的可以控制它的属性,那是否就无法来设置它的位置了呢?这时,该是VisualTreeHelper登场的时候了,不过在这之前,我们得先来看一个东西,所有的奥秘也在这个东西里面,那就是ChildWindow的Template。我们都知道,silverlight的控件都是在内部实现了它的基本模板(Template)和样式(Style)。
那么,我们接下来就来看看ChildWindow的Template中到底有什么东西。要想看它,有两个办法,一个是查看官方文档,里面有关于它的定义,还有一个方法就是通过Blend这个“神器”。在这里,我选择了第二个方法,我们打开Blend,然后定位到ChildWindow鼠标右击,选择编辑模板--编辑副本,确定之后,我们就能看到如下结果:

我们注意到,里面有一个Grid叫做ContentRoot,这并不是重点,其实,亮点在它的下面,看到了吧,在RenderTransform下有一组Transform,没错,找到了,奥秘就在这里,我们要想控制ChildWindow的位置,只要设置其中的TranslateTransform就行了,而要获取它,则是今天的主角VisualTreeHelper要做的事情了。接下来,我们就为ChildWindow写一个扩展方法SetStartLocation,通过它来设置弹出子窗口的位置:
1 public static class ChildWindowExtensions
2 {
3
4 public static void SetStartLocation(this ChildWindow childWindow, double x, double y)
5 {
6
7 var template = VisualTreeHelper.GetChild(childWindow, 0) as FrameworkElement;
8
9 var contentRoot = template.FindName("ContentRoot") as FrameworkElement;
10
11 var group = contentRoot.RenderTransform as TransformGroup;
12
13 TranslateTransform translateTransform = null;
14
15 foreach (var transform in group.Children.OfType<TranslateTransform>())
16 {
17
18 translateTransform = transform;
19
20 }
21
22 // 设置初始位置
23
24 translateTransform.X = x;
25
26 translateTransform.Y = y;
27
28 }
29
30
31
32
33
34 }
上面的代码通过VisualTreeHelper来得到可视化树的结构,然后进一步找到模板中我们需要的属性,最后设置它就行了,于是,我们就能在实际中使用它了,我们在主页面中添加
一个Button,并添加Click事件,在Click事件中生成ChildWindow对象并设置它的初始位置,最后show这个窗体:
ch = new ChildWindow1();
ch.SetStartLocation(100, 100);
ch.Show();
但是,运行后,当你点击Button的时候,会抛出一个异常,这是因为,此时ChildWindow还没有产生在可视化树上,所以你必须在它完成布局初始化,并产生在可视化树上的时候
才能,通过VisualTreeHelper找到需要的属性,我们修改代码如下:
1 private void button1_Click(object sender, RoutedEventArgs e)
2 {
3 ch = new ChildWindow1();
4 ch.Show();
5 ch.Loaded += new RoutedEventHandler(ch_Loaded);
6
7
8 }
9
10 void ch_Loaded(object sender, RoutedEventArgs e)
11 {
12 ch.SetStartLocation(100, 100);
13 }
14
这样,当你再点击Button的时候,子窗体将会在你设定的位置弹出,而不是在中心弹出。:)
1 public static class ChildWindowExtensions
2 {
3
4 public static void SetStartLocation(this ChildWindow childWindow, double x, double y)
5 {
6
7 var template = VisualTreeHelper.GetChild(childWindow, 0) as FrameworkElement;
8
9 var contentRoot = template.FindName("ContentRoot") as FrameworkElement;
10
11 var group = contentRoot.RenderTransform as TransformGroup;
12
13 TranslateTransform translateTransform = null;
14
15 foreach (var transform in group.Children.OfType<TranslateTransform>())
16 {
17
18 translateTransform = transform;
19
20 }
21
22 // 设置初始位置
23
24 translateTransform.X = x;
25
26 translateTransform.Y = y;
27
28 }
29
30
31
32
33
34 }
2 {
3
4 public static void SetStartLocation(this ChildWindow childWindow, double x, double y)
5 {
6
7 var template = VisualTreeHelper.GetChild(childWindow, 0) as FrameworkElement;
8
9 var contentRoot = template.FindName("ContentRoot") as FrameworkElement;
10
11 var group = contentRoot.RenderTransform as TransformGroup;
12
13 TranslateTransform translateTransform = null;
14
15 foreach (var transform in group.Children.OfType<TranslateTransform>())
16 {
17
18 translateTransform = transform;
19
20 }
21
22 // 设置初始位置
23
24 translateTransform.X = x;
25
26 translateTransform.Y = y;
27
28 }
29
30
31
32
33
34 }
ch = new ChildWindow1();
ch.SetStartLocation(100, 100);
ch.Show();
ch.SetStartLocation(100, 100);
ch.Show();
1 private void button1_Click(object sender, RoutedEventArgs e)
2 {
3 ch = new ChildWindow1();
4 ch.Show();
5 ch.Loaded += new RoutedEventHandler(ch_Loaded);
6
7
8 }
9
10 void ch_Loaded(object sender, RoutedEventArgs e)
11 {
12 ch.SetStartLocation(100, 100);
13 }
14
2 {
3 ch = new ChildWindow1();
4 ch.Show();
5 ch.Loaded += new RoutedEventHandler(ch_Loaded);
6
7
8 }
9
10 void ch_Loaded(object sender, RoutedEventArgs e)
11 {
12 ch.SetStartLocation(100, 100);
13 }
14
|
分类:
Silverlight闪烁
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构