[Silverlight] 写了两个方便 DOM 查找的扩展方法

Silverlight 中有所谓视觉树(Visual Tree)的概念,而 VisualTree 是一个运行时的概念,其实可以理解为一种 DOM.
其内容的来源可以是几个方面:

 1.静态 XAML 文件中创建的。
 2.用 XamlReadler.Load() 方法动态加载的 XAML 内容。
 3.完全通过代码创建的控件。

在 XAML 中我们通过 x:Name 来标识一个元素,但是光靠 Name 不能解决全部的问题,特别对于一些动态的场景而言。
有时候我们还需要根据控件的类型或者其他条件来查找节点。
比如:
    “给我找出当前这个控件在哪个 Tab 页(TabItem)中
    “找出祖先控件中谁实现了 IDialogHost 接口(准备显示一个对话框加载当前用户控件的内容)
等等类似的需求。

于是就有了下面两个方法:

using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;

namespace NeilChen.SilverlightExtensions
{
    
public static class DomExtensions
    {
        
/// <summary>
        
/// 查找祖先节点
        
/// </summary>
        
/// <typeparam name="T">目标节点的类型</typeparam>
        
/// <param name="child">起始节点</param>
        
/// <returns></returns>
        public static T FindAncestor<T>(this DependencyObject child) where T : class
        {
            var d 
= VisualTreeHelper.GetParent(child);
            
while (d != null && !(d is T))
            {
                d 
= VisualTreeHelper.GetParent(d);
            }
            
return d as T;
        }

        
/// <summary>
        
/// 查找某种类型的子孙节点
        
/// </summary>
        
/// <typeparam name="T">目标节点类型</typeparam>
        
/// <param name="parent">起始节点</param>
        
/// <returns>符合条件的节点集合</returns>
        public static IEnumerable<T> FindChildren<T>(this 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;
                }
            }
        }
    }
}


使用方法很简单。比如(还是拿对话框来举例):

IDialogHost host = this.FindAncestor<IDialogHost>();
if (host != null)
{
    host.ShowModalDialog(
this);
}


over.

posted on 2008-07-23 14:09  NeilChen  阅读(2047)  评论(8编辑  收藏  举报

导航