在Silverlight项目开发中,经常会把一个独立功能的控件封装成一个UserControl,然后供其他页面或者控件进行调用。前一段时间,在项目中遇到一个问题,需要在同一个页面重复调用多个相同的UserControl控件,然后在父页面中控制这些重复生成的子控件。由于很多控件是动态生成,数量也是动态控制,所以所有的操作都需要使用后台代码进行实现。
在上面的需求中需要用到Silverlight API中的VisualTreeHelper类,对于VisualTreeHelper类,有不少文章已经介绍过,该类可以对Silverlight可视化树进行遍历,该可视化树是逻辑对象树的一个子集。我们可以通过VisualTreeHelper提供的方法GetChild(),GetParent()和GetChildrenCount(),分别获取子控件,父控件以及子控件数量。
在实际项目中,为满足实际开发需求,对VisualTreeHelper的方法重新进行封装是非常必要的。
首先要介绍的Hleper方法是GetParentObject方法,获取父控件方法。该方法将根据当前控件,遍历查找其父控件是否存在。参数1是表示当前子控件名,参数2是要查询父控件名;使用VisualTreeHelper.GetParent方法获取当前父控件。
 1  public T GetParentObject<T>(DependencyObject obj, string name) where T : FrameworkElement
 2         {
 3             DependencyObject parent = VisualTreeHelper.GetParent(obj);
 4 
 5             while (parent != null)
 6             {
 7                 if (parent is T && (((T)parent).Name == name | string.IsNullOrEmpty(name)))
 8                 {
 9                     return (T)parent;
10                 }
11 
12                 parent = VisualTreeHelper.GetParent(parent);
13             }
14 
15             return null;
16         }
17 
另外一个Helper方法是GetChildObject,获取子控件方法。该方法将根据当前控件,遍历查找其子控件是否存在。参数1是表示当前父控件名,参数2是要查询子控件名;
 1 public T GetChildObject<T>(DependencyObject obj, string name) where T : FrameworkElement
 2         {
 3             DependencyObject child = null;
 4             T grandChild = null;
 5 
 6             for (int i = 0; i <= VisualTreeHelper.GetChildrenCount(obj) - 1; i++)
 7             {
 8                 child = VisualTreeHelper.GetChild(obj, i);
 9 
10                 if (child is T && (((T)child).Name == name | string.IsNullOrEmpty(name)))
11                 {
12                     return (T)child;
13                 }
14                 else
15                 {
16                     grandChild = GetChildObject<T>(child, name);
17                     if (grandChild != null)
18                         return grandChild;
19                 }
20             }
21 
22             return null;
23 
24         }
最后介绍一个Helper方法是GetChildObjects方法,该方法将把所有子控件作为List集合返回到客户端。其中第一个参数是父控件参数,而第二个参数是特定子控件名称,如果需要遍历全部子控件,第二个参数留空即可。
 1 public List<T> GetChildObjects<T>(DependencyObject obj, string name) where T : FrameworkElement
 2         {
 3             DependencyObject child = null;
 4             List<T> childList = new List<T>();
 5 
 6             for (int i = 0; i <= VisualTreeHelper.GetChildrenCount(obj) - 1; i++)
 7             {
 8                 child = VisualTreeHelper.GetChild(obj, i);
 9 
10                 if (child is T && (((T)child).Name == name || string.IsNullOrEmpty(name)))
11                 {
12                     childList.Add((T)child);
13                 }
14 
15                 childList.AddRange(GetChildObjects<T>(child,""));
16             }
17 
18             return childList;
19 
20         }
下面用一个例程演示使用方法:
使用方法很简单,首先创建基础控件:
 1 <UserControl x:Class="SLVisualTreeHelper.MainPage"
 2     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 5     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 6     mc:Ignorable="d"
 7     d:DesignHeight="300" d:DesignWidth="400">
 8 
 9     <Grid x:Name="LayoutRoot" Background="White">
10         <Grid.RowDefinitions>
11             <RowDefinition Height="Auto"></RowDefinition>
12             <RowDefinition Height="*"></RowDefinition>
13         </Grid.RowDefinitions>
14         <StackPanel x:Name="spDemoPanel" Orientation="Vertical" Grid.Row="0">
15             <TextBlock Margin="5">获取子控件和父控件演示</TextBlock>
16             <TextBlock Margin="5">专注Silverlight技术交流</TextBlock>
17             <TextBlock Margin="5">博客:http//jv9.cnblogs.com</TextBlock>
18             <Button x:Name="btDemoButton" Width="120" Height="40" Content="获取所有控件" Click="btDemoButton_Click" HorizontalAlignment="Left" Margin="5"/>
19             <Button x:Name="btModifyChild" Width="120" Height="40" Content="修改布局控件背景" Click="btModifyChild_Click" HorizontalAlignment="Left" Margin="5"/>
20             <Button x:Name="btModifyChilds" Width="120" Height="40" Content="批量修改控件字体尺寸" Click="btModifyChilds_Click" HorizontalAlignment="Left" Margin="5"/>
21         </StackPanel>
22         
23         <StackPanel x:Name="spResult" Grid.Row="1">
24             <TextBlock x:Name="tbResult"/>
25         </StackPanel>
26 
27     </Grid>
28 </UserControl>
29 
然后在后台代码,声明实例进行调用,
 1 namespace SLVisualTreeHelper
 2 {
 3     public partial class MainPage : UserControl
 4     {
 5         
 6         public MainPage()
 7         {
 8             InitializeComponent();
 9         }
10 
11         private void btDemoButton_Click(object sender, RoutedEventArgs e)
12         {
13             Globals VTHelper = new Globals();
14             StackPanel sp = VTHelper.GetChildObject<StackPanel>(this.LayoutRoot, "spDemoPanel");
15             Grid layoutGrid = VTHelper.GetParentObject<Grid>(this.spDemoPanel, "LayoutRoot");
16             List<TextBlock> textblock = VTHelper.GetChildObjects<TextBlock>(this.LayoutRoot, "");
17          
18            
19             if (sp != null)
20             {
21                 if (layoutGrid != null)
22                 {
23                     
24                     if (textblock.Count > 0)
25                     {
26                         tbResult.Text = "包含TextBlock控件数量为: " + textblock.Count.ToString() + "\n";
27                     }
28                     tbResult.Text += "获取父控件成功....\n" ;
29                 }
30                 tbResult.Text += "获取子控件成功....\n";
31             }
32         }
33 
34         private void btModifyChild_Click(object sender, RoutedEventArgs e)
35         {
36             Globals VTHelper = new Globals();
37             StackPanel sp = VTHelper.GetChildObject<StackPanel>(this.LayoutRoot, "spDemoPanel");
38             sp.Background = new SolidColorBrush(Colors.Purple); 
39         }
40 
41         private void btModifyChilds_Click(object sender, RoutedEventArgs e)
42         {
43             Globals VTHelper = new Globals();
44             List<TextBlock> textblock = VTHelper.GetChildObjects<TextBlock>(this.LayoutRoot, "");
45             foreach (TextBlock tmpTextblock in textblock)
46             {
47                 tmpTextblock.FontSize += 6;
48             }
49         }
50     }
51 }
其中Globals类中包含前文介绍的几个获取代码。
在线演示:
最后是源代码下载,项目是VS2010+Silverlight 4.

转载于:https://blog.51cto.com/kevinfan/340244

Silverlight获取子控件和父控件方法相关推荐

  1. android 控件覆盖关系,安卓子控件抢占父控件点击事件或者焦点问题

    开发中很常见的一个问题,项目中的lListview不仅仅是简单的文字,常常需要自己定义listview,自己的Adapter去继承BaseAdapter,在adapter中按照需求进行编写,问题就出现 ...

  2. WPF查找子控件和父控件方法

    原文:WPF查找子控件和父控件方法 public List<T> GetChildObjects<T>(DependencyObject obj, string name) w ...

  3. pyqt 子控件更新父控件ui

    可以用信号槽,好像专业点. 也可以直接用变量通信. 子控件更新父控件ui时,重新弹了一个窗口,父控件重新建了一个实例 仔细查原因 是子控件,父控件都有信号槽,相互连接,把关系搞串了,后来删掉一端的信号 ...

  4. android关于 子控件超出父控件范围的注意点

    通过 搜索引擎的搜索,我们知道了android:clipChildren = "false"  这个属性 可以让父view 在子view超出以后不切割子view. 那么我现在说几个 ...

  5. C# 在子窗体中调用父窗体的方法

    C# 在子窗体中调用父窗体的方法 在改软件的时候碰上一个非常麻烦的问题,查了好久才顺利解决 具体方法参考了 https://blog.csdn.net/lz00728/article/details/ ...

  6. 151202storyboard中, 设置子控件和父控件的高宽比

    选择子控件label,点control 连接到父控件view 松手后弹出对话框 选择高宽比,equal widths 或equal heights 然后点击Size inspector->Con ...

  7. window.open window.showModelDialog 打开一个新窗口/子窗口中调用父窗口的方法

    window.open 只打开一个窗口是将 oNewWindow   =   window   .   open   (   sURL   ,   sName   ,   sFeatures   , ...

  8. window.opener用法(在子窗体中获得父窗体的方法)

    window.opener 实际上就是通过window.open打开的窗体的父窗体. 比如在父窗体parentForm里面 通过 window.open("subForm.html" ...

  9. 超出父控件怎么才能点击

    首先:我们先总结一下控件不能交互的原因有哪些? // 1.控件的用户交互被关闭了! -> userInteractionEnable = NO[用户交互]!// 2.控件隐藏了! hidden ...

  10. Android中setLayoutParams要用父控件的LayoutParams

    这几天做程序想明白了一个问题,在此做一下记录. ActionBarCustomView customview = new ActionBarCustomView(context); ActionBar ...

最新文章

  1. java传值到sql decode语句_SQL之DECODE
  2. 思维导图 - 测试技术扩展:Postman接口测试、Sonar白盒测试、Sonic移动测试、Python操作FTP服务器
  3. Cortex - M3 位带别名首地址的计算方法
  4. python中时间处理_Python中处理时间的几种方法小结
  5. Jackson学习笔记
  6. 吴恩达DeepLearningCourse4-卷积神经网络
  7. appium + python 搭建
  8. linux 脚本调用企业微信_shell或python调用企业微信发送消息(实现报警功能)
  9. 获取随机数的方式Random类对象的方法 java 0913
  10. HDOJ 5087 Revenge of LIS II DP
  11. linux下hex文件到bin文件的格式转化,hex转换成bin文件小工具(HEX2BIN.EXE)下载_hex转换成bin文件小工具(HEX2BIN.EXE)官方下载-太平洋下载中心...
  12. 测试手机烧屏的软件,还能修手机烧屏?安卓手机屏幕测试神器
  13. 全面领跑中国DevOps云服务市场,为什么是华为云?
  14. 鸿蒙系统是不是无法注册gmail邮箱也无法正常使用youtube?
  15. 自制Openerp图表
  16. 3.1 Vendor Model浅析
  17. The Last Non-zero Digit
  18. win10家庭版计算机配置在哪里,Windows10家庭版没有组策略的解决方法
  19. 【CodeWars】Ones and Zeros
  20. Codeforces1153D-Serval and Rooted Tree(树形dp)

热门文章

  1. Android【报错】Description Resource Path Location Type Call requires API level 9 (current min is 8):
  2. 模仿QZONE挂图效果
  3. .NET/CLI元数据中使用的压缩整数
  4. 深入理解JVM-java内存区域与内存溢出异常
  5. ormlite的使用方法
  6. 每日英语:A Chinese Soccer Club Has Won Something!
  7. Windows server 2019 - Raid1 搭建+测试
  8. python3.8+mysql+pymysql安装
  9. C++智能指针的实现与使用(详解)
  10. KVM详解(一)——KVM基础知识