在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. UVa 10474 Where is the Marble

    题意:给出一列数,先排序,再查找学习了sort函数,lower_bound函数sort:可以给任意对象排序(包括自己定义的)(前提是定义好了‘<’运算符)lower_bound:查找大于或者等于 ...

  2. 【Java】MD5加密

    package sdfg; import java.math.BigInteger; import java.security.MessageDigest; import java.security. ...

  3. 机器学习(二)——K-均值聚类(K-means)算法

    最近在看<机器学习实战>这本书,因为自己本身很想深入的了解机器学习算法,加之想学python,就在朋友的推荐之下选择了这本书进行学习,在写这篇文章之前对FCM有过一定的了解,所以对K均值算 ...

  4. 初步认识mongodb文件

    初步认识mongo. README文件介绍压缩包中各个文件的功能. bin/mongod - MongoDB server bin/mongo - MongoDB client bin/mongodu ...

  5. Android View绘制13问13答

    1.View的绘制流程分几步,从哪开始?哪个过程结束以后能看到view? 答:从ViewRoot的performTraversals开始,经过measure,layout,draw 三个流程.draw ...

  6. Android 自定义view中的属性,命名空间,以及tools标签

    昨日看到有人在知乎上问这3个琐碎的小知识点,今天索性就整理了一下,其实这些知识点并不难,但是很多开发者平时很少注意到这些, 导致的后果就是开发的时候 经常会被ide报错,开发效率很低,或者看开源代码的 ...

  7. Python中的sorted函数以及operator.itemgetter函数

    operator.itemgetter函数operator模块提供的itemgetter函数用于获取对象的哪些维的数据,参数为一些序号(即需要获取的数据在对象中的序号),下面看例子. a = [1,2 ...

  8. 深入理解JavaScript闭包(closure)

    最近在网上查阅了不少javascript闭包(closure)相关的资料,写的大多是非常的学术和专业.对于初学者来说别说理解闭包了,就连文字叙述都很难看懂.撰写此文的目的就是用最通俗的文字揭开Java ...

  9. 嵌入式 GDB调试死锁示例

    死锁:一种情形,此时执行程序中两个或多个线程发生永久堵塞(等待),每个线程都在等待被 其他线程占用并堵塞了的资源.例如,如果线程A锁住了记录1并等待记录2,而线程B锁住了记录2并等待记录1,这样两个线 ...

  10. 11、NFC技术:NDEF Uri格式解析

    NDEF Uri格式规范 与NDEF文本格式一样,存储在NFC标签中的Uri也有一定的格式 http://www.nfc-forum.org/specs/spec_dashboard 编写可以解析Ur ...