zoukankan      html  css  js  c++  java
  • c# 扩展方法奇思妙用高级篇六: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     }

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

  • 相关阅读:
    python 模拟浏览器
    转:如何评价架构的优劣
    转:DotNET企业架构应用实践架构师成长之路如何成为优秀架构师
    转:大规模网站架构实战之体系结构(一)
    转:Twitter的设计原则
    转:关于大型asp.net应用系统的架构—如何做到高性能高可伸缩性
    转:我眼中的Visual Studio 2010架构工具
    转:解剖Twitter
    转:Discuz!NT前台模型架构(MVC)
    转: "HTTP 错误 401.1 未经授权:访问由于凭据无效被拒绝"的另类解决方案
  • 原文地址:https://www.cnblogs.com/ywsoftware/p/3128774.html
Copyright © 2011-2022 走看看