在Web开发中,jQuery提供了功能异常强大的$选择器来帮助我们获取页面上的对象。但在WinForm中,.Net似乎没有这样一个使用起来比较方便的选择器。好在我们有扩展方法,可以很方便的打造一个。

我们先看几个类图,深入认识一下我们常用的WinForm控件:

图1  ScrollableControl类图

图2  ButtonBase类图

图3  TextBoxBase类图

图4  ListControl类图

图5  Label类图

图6  其它常用

从图1中可以看出,Form与Button、Label一样,也是一个Control。

WinForm中的一些控件(如Form、GroupBox、Panel)可以包含其它控件,我们可以通过Control类的Controls属性进行遍历。控件是可以层层包含的,如下图:

图7  示例窗体

Form1是顶级控件,它包含了四个子控件:groupBox1、groupBox2、button1、button2。groupBox1和groupBox2中也包含了多个控件。层层包含最终形成了一个树型结构。

我们打造的WinForm的控件选择器,实质上就是一个树的遍历器。下是就是该选择器的参考实现代码:


 1     public static IEnumerable<T> GetControls<T>(this Control control, Func<T, bool> filter) where T : Control

 2     {

 3         foreach (Control c in control.Controls)

 4         {

 5             if (c is T)

 6             {

 7                 T t = c as T;

 8                 if (filter != null)

 9                 {

10                     if (filter(t))

11                     {

12                         yield return t;

13                     }

14                     else

15                     {

16                         foreach (T _t in GetControls<T>(c, filter))

17                             yield return _t;

18                     }

19                 }

20                 else

21                     yield return t;

22             }

23             else

24             {

25                 foreach (T _t in GetControls<T>(c, filter))

26                     yield return _t;

27             }

28         }

29     }

(代码中存在一处bug,请参见斯克迪亚的回复#4楼

有了GetControls选择器,我们就可以在WinForm中进行一些“复杂”应用,示例如下(以图7为例):


 1     // 构造函数

 2     public Form1()

 3     {

 4         InitializeComponent();

 5         //禁用所有Button

 6         this.GetControls<Button>(null).ForEach(b => b.Enabled = false);

 7         //反选groupBox1中CheckBox

 8         this.GetControls<CheckBox>(c => c.Parent == groupBox1)

 9             .ForEach(c => c.Checked = !c.Checked);

10         //将label1的前景色设为红色

11         this.GetControls<Label>(l => l.Name == "label1").FirstOrDefault().ForeColor

12             = Color.Red;

13     }

附上常用的ForEach扩展:

1     public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)

2     {

3         foreach (var item in source) 

4             action(item);

5     }

感觉如何?欢迎批评指正!(代码仅供参考)

C# 扩展方法奇思妙用高级篇六:WinForm 控件选择器的更多相关文章

  1. c# 扩展方法 奇思妙用 高级篇 九:OrderBy(string propertyName, bool desc)

    下面是 Queryable 类 中最常用的两个排序的扩展方法: 1 2 public static IOrderedQueryable<TSource> OrderBy<TSourc ...

  2. c# 扩展方法奇思妙用基础篇八:Distinct 扩展(转载)

    转载地址:http://www.cnblogs.com/ldp615/archive/2011/08/01/distinct-entension.html 刚看了篇文章 <Linq的Distin ...

  3. c# 扩展方法奇思妙用基础篇八:Distinct 扩展

    刚看了篇文章 <Linq的Distinct太不给力了>,文中给出了一个解决办法,略显复杂. 试想如果能写成下面的样子,是不是更简单优雅 var p1 = products.Distinct ...

  4. c# 扩展方法奇思妙用基础篇五:Dictionary<TKey, TValue> 扩展

    Dictionary<TKey, TValue>类是常用的一个基础类,但用起来有时确不是很方便.本文逐一讨论,并使用扩展方法解决. 向字典中添加键和值 添加键和值使用 Add 方法,但很多 ...

  5. c# 扩展方法奇思妙用基础篇九:Expression 扩展

    http://www.cnblogs.com/ldp615/archive/2011/09/15/expression-extension-methods.html .net 中创建 Expressi ...

  6. c# 扩展方法奇思妙用

    # 扩展方法出来已久,介绍扩展方法的文章也很多,但都是笼统的.本人最近一直在思考扩展方法的应用,也悟出了一些,准备将这最近一段时间对扩展方法的思考,写成一个系列文章.每个文章只介绍一个应用方面,篇幅不 ...

  7. c# 扩展方法奇思妙用集锦

    本文转载:http://www.cnblogs.com/ldp615/archive/2009/08/07/1541404.html 其中本人觉得很经典的:c# 扩展方法奇思妙用基础篇五:Dictio ...

  8. [转]在WPF中使用WinForm控件方法

    本文转自:http://blog.csdn.net/lianchangshuai/article/details/6415241 下面以在Wpf中添加ZedGraph(用于创建任意数据的二维线型.条型 ...

  9. 多线程访问winform控件出现异常的解决方法

    一.  多线程访问winform控件出现异常的解决方法 1.  问题描述<1> 如果创建某控件的线程之外的其他线程试图调用该控件,则会引发一个 InvalidOperationExcept ...

随机推荐

  1. ecshop 删除随机版权

    删除随机版权: js/commjon.js -> onload = function()函数

  2. Android如何获取系统高度、标题栏和状态栏高度

    在android应用中,有时需要计算个View的位置,导致需要计算状态栏高度,标题栏高度等信息.为以后方便,在此做个简单记录. 晒代码前先了解一下android屏幕区域的划分,如下图(该图引用自此文h ...

  3. python知识:json格式文本;异常处理;字符串处理;unicode类型和str类型转换

    python进程中的实例和json格式的字符串之间的映射关系是非常直接的,相当于同一个概念被编码成不同的表示: stream in json form ----json.loads(str)----- ...

  4. 【Sass初级】开始使用Sass和Compass

    转自:http://www.w3cplus.com/preprocessor/beginner/getting-started-with-sass-and-compass.html 如果你的朋友.同事 ...

  5. AsciiDoc

    AsciiDoc Text based document generation AsciiDoc Home Page Table of Contents Introduction Overview a ...

  6. markdown插件学习

    1.Markdown的定义 Markdown是一种可以使用普通文本编辑器编写的标记语言,通过简单的标记语法,它可以使普通文本内容具有一定的格式.它用简洁的语法代替排版,而不像一般我们用的字处理软件Wo ...

  7. [Everyday Mathematics]20150223

    是否存在 $3\times 3$ 阶实方阵 $A$ 使得 $\tr A=0$ 且 $A^2+A^T=I$?

  8. c++中调用cygwin/x使用ncl

    1.C++中调用程序:   ShellExecute(NULL,L"open",L"cmd.exe",L"/c d: & cd cygwin ...

  9. 【quick-cocos2d-x】Lua 面向对象(OOP)编程与元表元方法

    版权声明:本文为博主原创文章,转载请注明出处. 面向对象是一种对现实世界理解和抽象的方法,是计算机编程技术发展到一定阶段后的产物. 早期的计算机编程是基于面向过程的方法,通过设计一个算法就可以解决当时 ...

  10. SynchronousQueue

    SynchronousQueue是一个没有数据缓冲的BlockingQueue,生产者线程对其的插入操作put必须等待消费者的移除操作take,反过来也一样. 不像ArrayBlockingQueue ...