WPF利用VisualTreeHelper遍历寻找对象的指定子级对象或者指定父级对象
转载 https://www.cnblogs.com/dotnetHui/p/8342398.html
微软在VisualTreeHelper类中,提供了一些实用工具方法,用于执行涉及可视化树中的节点的常规任务,VisualTreeHelper 类中的一些方法可以接受表示任意一种可视对象类型的 DependencyObject 值。
这里我们将要用到两个方法分别是:VisualTreeHelper.GetChild()和VisualTreeHelper.GetParent()。
使用VisualTreeHelper
模拟场景搭建
新建一个WPF工程,命名为VisualTreeHelperDemo。
假设我们有如下如所示的一个主窗体,窗体的内容容器为一个name=”TopGrid”的Grid控件,它包含了上下两个子级Grid,每个子级Grid中各自包含了一个Button。
MainWindow.xaml代码如下:
<Window x:Class="VisualTreeHelper.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid Name="TopGrid"> <Grid.RowDefinitions> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> </Grid.RowDefinitions> <Grid > <Button Content="Button1" Name="btn_One" VerticalAlignment="Center" HorizontalAlignment="Center"> </Button> </Grid> <Grid Grid.Row="1"> <Button Content="Button2" Name="btn_Two" VerticalAlignment="Center" HorizontalAlignment="Center"> </Button> </Grid> </Grid> </Window>
MainWindow.xaml代码如下:
<Window x:Class="VisualTreeHelper.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid Name="TopGrid"> <Grid.RowDefinitions> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> </Grid.RowDefinitions> <Grid > <Button Content="Button1" Name="btn_One" VerticalAlignment="Center" HorizontalAlignment="Center"> </Button> </Grid> <Grid Grid.Row="1"> <Button Content="Button2" Name="btn_Two" VerticalAlignment="Center" HorizontalAlignment="Center"> </Button> </Grid> </Grid> </Window>
遍历寻找子级对象
现在我们来寻找TopGrid所有Button子级对象,并输出它们的名称。
打开MainWindow.xaml.cs文件,添加寻找子级对象的代码如下:
/// <summary> /// 利用visualtreehelper寻找对象的子级对象 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="obj"></param> /// <returns></returns> List<T> FindVisualChild<T>(DependencyObject obj) where T : DependencyObject { try { List<T> TList = new List<T> { }; for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++) { DependencyObject child = VisualTreeHelper.GetChild(obj, i); if (child != null && child is T) { TList.Add((T)child); List<T> childOfChildren = FindVisualChild<T>(child); if (childOfChildren != null) { TList.AddRange(childOfChildren); } } else { List<T> childOfChildren = FindVisualChild<T>(child); if (childOfChildren != null) { TList.AddRange(childOfChildren); } } } return TList; } catch (Exception ee) { MessageBox.Show(ee.Message); return null; } }
在btn_One_Click事件里面书写代码如下:
/// <summary> /// 窗体加载事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btn_One_Click(object sender, RoutedEventArgs e) { string btnName = ""; List<Button> btnList = FindVisualChild<Button>(TopGrid); foreach (Button item in btnList) { btnName += string.IsNullOrEmpty(btnName) ? item.Name.ToString() : "," + item.Name.ToString(); } Show(string.Format(TopGrid.Name.ToString()+"共有{0}个Button,名称分别为{1}", btnList.Count, btnName)); }
运行程序,点击Button1,结果如下图:
遍历寻找父级对象
现在我们来遍历Button2的父级对象,获得其所有父级对象的信息,并且展示。
打开MainWindow.xaml.cs文件,添加寻找父级对象的代码如下:
/// <summary> /// 利用VisualTreeHelper寻找指定依赖对象的父级对象 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="obj"></param> /// <returns></returns> public static List<T> FindVisualParent<T>(DependencyObject obj) where T : DependencyObject { try { List<T> TList = new List<T> { }; DependencyObject parent = VisualTreeHelper.GetParent(obj); if (parent != null && parent is T) { TList.Add((T)parent); List<T> parentOfParent = FindVisualParent<T>(parent); if (parentOfParent !=null) { TList.AddRange(parentOfParent); } } else if ( parent != null ) { List<T> parentOfParent = FindVisualParent<T>(parent); if (parentOfParent != null) { TList.AddRange(parentOfParent); } } return TList; } catch (Exception ee) { MessageBox.Show(ee.Message); return null; } }
在btn_Two_Click中添加代码如下:
/// <summary> /// 遍历Button2父级对象信息 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btn_Two_Click(object sender, RoutedEventArgs e) { string parentName = ""; List<Grid> gridList = FindVisualParent<Grid>(btn_Two); foreach (Grid item in gridList) { parentName += string.IsNullOrEmpty(parentName) ? item.Name.ToString() : "," + item.Name.ToString(); } MessageBox.Show(string.Format(btn_Two.Name.ToString() + "共有{0}个逻辑父级,名称分别为{1}", gridList.Count, parentName)); }
运行程序,点击Button2,效果如下:
结果表明遍历成功。