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的时候,子窗体将会在你设定的位置弹出,而不是在中心弹出。:)

相关文章
相关标签/搜索