必须填写至少10个字的日志
nnhy authored at 2012-07-27 18:48:21
6.77 KiB
X
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
using System.Web;
using System.Web.UI;
#if NET4
using System.Linq;
#else
using NewLife.Linq;
#endif
using NewLife.Reflection;

namespace NewLife.Web
{
    /// <summary>控件助手</summary>
    public static class ControlHelper
    {
        /// <summary>查找指定类型的子孙控件</summary>
        /// <typeparam name="T">目标控件类型</typeparam>
        /// <param name="control">父控件,从该控件开始向下进行广度搜索</param>
        /// <param name="id">控件ID,不指定表示不限制</param>
        /// <returns></returns>
        public static T FindControl<T>(Control control, String id) where T : Control
        {
            if (control == null) return null;

            // 准备队列,进行广度搜索
            Queue<Control> queue = new Queue<Control>();
            queue.Enqueue(control);

            while (queue.Count > 0)
            {
                control = queue.Dequeue();

                // 类型匹配
                if (control is T)
                {
                    // 没有指定控件ID,或者控件ID匹配
                    //if (String.IsNullOrEmpty(id) || String.Equals(control.ID, id, StringComparison.OrdinalIgnoreCase))
                    if (id.IsNullOrWhiteSpace() || id.EqualIgnoreCase(control.ID))
                        return control as T;
                }

                // 虽然类型匹配不一定成功,但是子控件还是要入队的
                if (control.Controls != null && control.Controls.Count > 0)
                {
                    foreach (Control item in control.Controls)
                    {
                        queue.Enqueue(item);
                    }
                }
            }

            return null;
        }

        /// <summary>查找指定控件附近的控件,向上搜索</summary>
        /// <typeparam name="T">目标控件类型</typeparam>
        /// <param name="control">指定控件</param>
        /// <param name="id">控件ID,不指定表示不限制</param>
        /// <returns></returns>
        public static T FindControlUp<T>(Control control, String id) where T : Control
        {
            if (control == null) return null;

            // 准备队列,进行广度搜索
            Queue<Control> queue = new Queue<Control>();
            queue.Enqueue(control);

            // 已经分析过的
            List<Control> parsed = new List<Control>();
            parsed.Add(control);

            while (queue.Count > 0)
            {
                control = queue.Dequeue();

                // 类型匹配
                if (control is T)
                {
                    // 没有指定控件ID,或者控件ID匹配
                    if (String.IsNullOrEmpty(id) || String.Equals(control.ID, id, StringComparison.OrdinalIgnoreCase))
                        return control as T;
                }

                // 虽然类型匹配不一定成功,但是遍历还是需要继续的
                Control parent = control.Page;
                if (parent == null) continue;

                if (parent.Controls != null && parent.Controls.Count > 0)
                {
                    foreach (Control item in parent.Controls)
                    {
                        if (!parsed.Contains(item))
                        {
                            queue.Enqueue(item);
                            parsed.Add(item);
                        }
                    }
                }
            }

            return null;
        }

        /// <summary>在页面查找指定ID的控件,采用反射字段的方法,避免遍历Controls引起子控件构造</summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="id"></param>
        /// <returns></returns>
        public static T FindControlInPage<T>(String id) where T : Control
        {
            if (HttpContext.Current == null) return null;

            IHttpHandler handler = HttpContext.Current.Handler;
            if (handler == null) return null;

            FieldInfoX fix = null;
            if (!String.IsNullOrEmpty(id))
            {
                fix = FieldInfoX.Create(handler.GetType(), id);
            }
            else
            {
                Type t = typeof(T);
                FieldInfo fi = handler.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault(item => item.FieldType == t);
                if (fi != null) fix = FieldInfoX.Create(fi);
            }

            if (fix == null) return null;

            return fix.GetValue(handler) as T;
        }

        /// <summary>根据字段查找指定ID的控件,采用反射字段的方法,避免遍历Controls引起子控件构造</summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="control">容器</param>
        /// <param name="id"></param>
        /// <returns></returns>
        public static T FindControlByField<T>(Control control, String id) where T : Control
        {
            if (control == null) return null;

            FieldInfoX fix = null;
            if (!String.IsNullOrEmpty(id))
            {
                fix = FieldInfoX.Create(control.GetType(), id);
            }
            else
            {
                Type t = typeof(T);
                FieldInfo fi = control.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault(item => item.FieldType == t);
                if (fi != null) fix = FieldInfoX.Create(fi);
            }

            if (fix == null) return null;

            return fix.GetValue(control) as T;
        }

        /// <summary>查找控件的事件</summary>
        /// <param name="control"></param>
        /// <param name="eventName"></param>
        /// <returns></returns>
        public static Delegate FindEventHandler(Control control, String eventName)
        {
            if (control == null) return null;
            if (String.IsNullOrEmpty(eventName)) return null;

            var pix = PropertyInfoX.Create(control.GetType(), "Events");
            if (pix == null) return null;

            EventHandlerList list = pix.GetValue(control) as EventHandlerList;
            if (list == null) return null;

            var fix = FieldInfoX.Create(control.GetType(), eventName);
            if (fix == null && !eventName.StartsWith("Event", StringComparison.Ordinal)) fix = FieldInfoX.Create(control.GetType(), "Event" + eventName);
            if (fix == null) return null;

            return list[fix.GetValue(control)];
        }
    }
}