c# 扩展方法奇思妙用高级篇六:WinForm 控件选择器

摘要:
但在WinFormNet中似乎没有这样一个方便的选择器。让我们看一下几个类图,以更深入地了解我们常用的WinForm控件:图1ScrollableControl类图图2ButtonBase类图图3TextBoxBase类图图4ListControl类图图5Label类图图6。从图1中可以看出,Form与Button和Label一样,也是一个控件。WinForm中的某些控件可以包含其他控件。我们可以遍历Control类的Controls属性。我们构建的WinForm控件选择器本质上是一个树遍历器。

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

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

ScrollableControl 

图1  ScrollableControl类图

ButtonBase图2  ButtonBase类图

TextBoxBase

图3  TextBoxBase类图

ListControl

图4  ListControl类图

Label

图5  Label类图

Other

图6  其它常用

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

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

Form1 

图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 控件选择器》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇openlayers3入门教程开源CRM和ERP撑起后台系统能走多远下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

C#客户端(WinForm)开机自动启动实现

/// <summary> ///修改程序在注册表中的键值 /// </summary> /// <param name="isAuto">true:开机启动,false:不开机自启</param> private voi...

WinForm跨线程访问控件异常

WinForm跨线程访问控件异常 最近做了个WinForm的小项目,遇到个简单的问题记录下。需求:点击”下载“,显示正在下载,下载完后更新状态为”ready“(要求用多线程,避免前台卡死)。 做法 新建一个线程,在新线程中下在更新控件状态,报异常跨线程程访问控件(当然可以通过关闭跨线程访问控件检验解决,不鼓励这么做)。应该C#5.0版本添加的任务Task异...

WinForm实现鼠标悬停显示控件

在某些需频繁操作的环节中,为提高效率、减少劳动,可以在操作细节上下功夫,以带来更好的用户体验。 今天介绍的鼠标悬停显示功能就是一例,看似仅仅节省了一次点击,实则在繁复操作中能够为用户节约很多体力,提高舒适度。 本例中的基本需求是: 鼠标移入设置区域后,直接弹出详尽设置内容,并当进行了设置或鼠标移出弹出的设置区域后,自动关闭弹出的设置区域。 在这里,我设计...

C#写的 电子邮件客户端(winform窗体)

如果用QQ邮箱测试需要在邮箱里面设置里面开启POPSMTP协议。并用获取授权码输入到密码框。 添加引用 using System.Net.Mail;using System.Net; 实例化:MailMessage mmsg = new MailMessage(); /// <summary> ///发送电子...

C#多功能DataGridView打印类(WinForm)

usingSystem;usingSystem.Collections;usingSystem.ComponentModel;usingSystem.Drawing;usingSystem.Drawing.Printing;usingSystem.Data;usingSystem.Windows.Forms;namespaceWeightSystem{pu...

winform中如何在TextBox中只能输入数字(可以带小数点)

可以采用像web表单验证的方式,利用textbox的TextChanged事件,每当textbox内容变化时,调用正则表达式的方法验证,用一个label在text后面提示输入错误,具体代码如下: private void textBox1_TextChanged(objectsender, EventArgs e) {...