• 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 
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    表数据转换为insert语句
    Google Map Api 谷歌地图接口整理
    VS预生成事件命令行 和 生成后事件命令行
    C#程序开机运行
    枚举数据源化
    winform分页管理
    数据库访问驱动
    sql时间格式
    sysobjects.xtype介绍
    编码标准的多样性
  • 原文地址:https://www.cnblogs.com/star250/p/2098156.html
Copyright © 2020-2023  润新知