zoukankan      html  css  js  c++  java
  • VisualTreeHelper 可视化树 逻辑树

    VisualTreeHelper

    Silverlight中只有可视化树,没有WPF中的逻辑树,这一点可从SL的sdk文档中得到印证:

    可视化树概念也存在于 WPF 中,它与 Silverlight 的可视化树概念类似。然而,一个显著的差异是 WPF 还提供一个附加的筛选器或对象树(称为"逻辑树")的概念。逻辑树概念与某些属性系统行为相关。Silverlight 不通过帮助器类来公开此逻辑树。Silverlight 中的确存在某些(但并非所有)相关的属性行为,但由于没有用于访问这些行为的帮助器 API,因此,逻辑树概念在 Silverlight 中将没有用武之地,因此本文档不讨论它。缺少逻辑树而引发的一个很小的兼容性问题是:FrameworkElement..::..Parent 属性行为在 Silverlight 版本 3 中是不同的,它实际上报告可视化树父项。

    利用XamlPad,可以查看简单xaml(指不加载第三方程序集的xaml)的对象树:

    xamlpad程序安装silverlight的sdk后,默认安装于x:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\下

    如下图:


    从上图可以看到,一个普通的Button控件,在可视化(对象)树里表现为:ButtomChrome,ContentPresenter,TextBlock的组合

    另外Silverlight中提供了一个VisualTreeHelper工具类,用于操作可视化树,里面有4个静态方法:

    官方解释如下:

     FindElementsInHostCoordinates  检索一组对象,这些对象位于某一对象的坐标空间的指定点或 Rect 内。 
     GetChild 使用提供的索引,通过检查可视化树获取所提供对象的特定子对象。 
     GetChildrenCount 返回在可视化树中在某一对象的子集合中存在的子级的数目。 
     GetParent 返回可视化树中某一对象的父对象。

    通俗点说:FindElementsInHostCoordinates常用于对象的碰撞检测,GetChild用于获取下级子对象(注意仅仅是下级,而非所有子对象,如果要获取所有子对象,需要自己写代码遍历),GetChildrenCount用于获取下级子对象的个数,GetParent用于获取某对象的上级子对象 

    测试代码:

    代码
    <UserControl x:Class="ToolsTest.MainPage"
        xmlns
    ="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x
    ="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d
    ="http://schemas.microsoft.com/expression/blend/2008" 
        xmlns:mc
    ="http://schemas.openxmlformats.org/markup-compatibility/2006" 
        mc:Ignorable
    ="d" d:DesignWidth="640" d:DesignHeight="480">
      
    <Grid x:Name="LayoutRoot">      
            
    <StackPanel x:Name="sp" HorizontalAlignment="Left">
                
    <TextBlock Text="Test TextBlock" Height="25" Width="100" x:Name="txt"></TextBlock>
                
    <Button x:Name="btn1" Content="button1" Height="25" Width="100" ></Button>
                
    <StackPanel x:Name="sp2">
                    
    <Button x:Name="btn2" Content="button2" Height="25" Width="100" ></Button>
                
    </StackPanel>
                
    <Button x:Name="btn3" Content="button3"></Button>
            
    </StackPanel>
            
    <Button x:Name="btnClick" Content="Test" Height="22" Width="80" HorizontalAlignment="Center" VerticalAlignment="Bottom" Click="btnClick_Click" ></Button>
      
    </Grid>
    </UserControl>

     

     

    代码
    using System.Linq;
    using System.Windows;
    using System.Collections.Generic;
    using System.Windows.Controls;
    using System.Windows.Media;


    namespace ToolsTest
    {
        
    public partial class MainPage : UserControl
        {
            
    public MainPage()
            {
                InitializeComponent();
            }

            
    private void btnClick_Click(object sender, RoutedEventArgs e)
            {
                
    int _childCount = VisualTreeHelper.GetChildrenCount(this);
                MessageBox.Show(
    "MainPage下级子对象总数:" + _childCount.ToString());//就是一个Grid,所以返回1

                IEnumerable
    <Button> AllButtons = FindChildren<Button>(this);//得到所有的Buttons

                
    int i =0;
                
    foreach (Button btn in AllButtons)
                {
                    i
    ++;
                    MessageBox.Show(
    string.Format("第{0}个按钮[{1}]的内容为:{2}",i,btn.Name,btn.Content));                
                }

                StackPanel sp 
    = VisualTreeHelper.GetParent(btn2) as StackPanel;
                MessageBox.Show(
    string.Format("{0}的上级对象是{1}",btn2.Content,sp.Name));

                Rect rect 
    = new Rect(0010025);

                IEnumerable
    <UIElement> check = VisualTreeHelper.FindElementsInHostCoordinates(rect, this); //检测MainPage的0,0到100,25矩形区域内有哪些元素

                
    foreach (UIElement item in check)
                {
                    
    string _name = item.GetValue(NameProperty).ToString();
                    
    if (_name.Length > 0)
                    {
                        MessageBox.Show(_name);
                    }
                }           
            }


            
    /// <summary>
            
    /// 来自博客园"木野狐"的特定类型子对象方法
            
    /// </summary>
            
    /// <typeparam name="T"></typeparam>
            
    /// <param name="parent"></param>
            
    /// <returns></returns>
            public IEnumerable<T> FindChildren<T>(DependencyObject parent) where T : class
            {
                var count 
    = VisualTreeHelper.GetChildrenCount(parent);
                
    if (count > 0)
                {
                    
    for (var i = 0; i < count; i++)
                    {
                        var child 
    = VisualTreeHelper.GetChild(parent, i);
                        var t 
    = child as T;
                        
    if (t != null)
                            
    yield return t;

                        var children 
    = FindChildren<T>(child);
                        
    foreach (var item in children)
                            
    yield return item;
                    }
                }
            }
        }
    }

    最后关于对象碰撞检测,推荐一篇不错的文章: http://www.andybeaulieu.com/Home/tabid/67/EntryID/160/Default.aspx 里面对于矢量对象的检测就是利用的FindElementsInHostCoordinates

     

    作者:菩提树下的杨过
    出处:http://yjmyzz.cnblogs.com 
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    动态传参
    函数的介绍
    文件的操作
    send email with formatted table
    minimize and close window with customed winform
    python algorithm
    something important about docker
    book list
    which language is suitable for what to do
    Find Duplicate Items in list fast
  • 原文地址:https://www.cnblogs.com/star250/p/2098156.html
Copyright © 2011-2022 走看看