自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

詳解WinForm通用速選組件的構(gòu)建

開發(fā) 后端
在這里我們要討論的是WinForm通用速選組件的構(gòu)建,希望對大家了解WinForm組件有所幫助。

對于WinForm組件,大家并不陌生。在這里我們將為大家講解WinForm通用速選組件的構(gòu)建,這也是通往WinForm開發(fā)的必經(jīng)之路。

用戶界面中,需要用戶進(jìn)行多項(xiàng)選擇時(shí),我們通常會提供一組快速選擇(以下簡稱速選)按鈕:全選、反選、清空,以方便用戶操作。本文章將會構(gòu)建一個(gè)通用速選組件來簡化操作,使用之后,您不需要編寫任何代碼,只需設(shè)置兩個(gè)屬性便可讓一個(gè)控件擁有速選的功能。

WinForm中常見的幾種多選形式如下圖:

SelectComponent 

圖1

我們暫且將用于顯示選項(xiàng)的控件叫做“選項(xiàng)控件”,全選、反選、清空叫做“速選按鈕”。

四種形式采用了不同的控件用作選項(xiàng)控件、速選按鈕:

  選項(xiàng)控件 速選按鈕
形式一 CheckedListBox Label
形式二 CheckBox LinkLabel
形式三 TreeView Button
形式四 DataGridView PictureBox

實(shí)際使用中還可能會有其它形式的選項(xiàng)控件和速選按鈕,根據(jù)使用場合不同,選項(xiàng)控件和速選按鈕可以任意組合。這給我們編程帶來了麻煩,選項(xiàng)控件沒有統(tǒng)一的訪問接口,換一個(gè)選項(xiàng)控件就要編寫不同的選擇代碼。

想要將全選、反選、清空的選擇邏輯提取出來還真不容易。于是很多程序員就選擇了針對實(shí)際應(yīng)用的組合(如形式一,CheckedListBox + Label)進(jìn)行直接編碼。這樣導(dǎo)致大量相似的代碼充斥在項(xiàng)目之中,會帶來以下問題:

  1. 重復(fù)的編碼、調(diào)試、測試(主要是界面)工作;
  2. 一旦選項(xiàng)控件發(fā)生改變,就必須修改代碼,修改后還要測試;(可能性比較大,可能客戶不喜歡形式一,非要你修改成形式二)

這樣的直接編碼實(shí)際上已經(jīng)違反了DRY原則,我們應(yīng)該糾正。

面向?qū)ο笠笪覀兎庋b變化,我們這里不變的是速選的邏輯,變化的是選項(xiàng)控件和速選按鈕,變化是兩個(gè)方向的,有點(diǎn)接近橋模式的應(yīng)用場景了。不過我對設(shè)計(jì)模式了解不深,不敢冒用,而且感覺這里速選按鈕的變化是比較簡單的,至少它們都有一個(gè)Click事件,也可以認(rèn)為是不變的。

 

#T#

我們采用另外一種途徑,.Net其實(shí)已經(jīng)給我們提供了一種擴(kuò)展控件功能的方式(也正體現(xiàn)了面向?qū)ο蟮腛CP原則),可以讓我們給控件賦予額外的功能。我們來看一個(gè)重要的接口:IExtenderProvider 接口,位于System.ComponentModel命名空間下。實(shí)現(xiàn)了這個(gè)接口的組件有ToolTip、ErrorProvider等,ToolTip、ErrorProvider這兩個(gè)組件可以向其它組件(控件是組件的一種)提供額外的功能,ToolStip能讓其它控件在用戶鼠標(biāo)懸停時(shí)彈出一個(gè)小框顯示一些提示信息,ErrorProvider則能讓控件顯式錯(cuò)誤信息。

我們要做的就是創(chuàng)建一個(gè)新的組件,實(shí)現(xiàn)IExtenderProvider接口,向控件(Button、Label等)提供速選的功能。這個(gè)組件我已經(jīng)完成了,名字叫FastSelect,先不考慮實(shí)現(xiàn)原理、如何實(shí)現(xiàn),我們先看下如何使用吧:

FastSelect是一個(gè)組件,會自動顯示在工具箱中,將其拖入窗體,將會顯示在設(shè)計(jì)器下方。

FastSelect組件

圖2

選中全選按鈕(label1),屬性顯示窗口如下圖:

FastSelect2

圖3

分組中出現(xiàn)了一個(gè)新的分組:速選,其中有如上圖兩個(gè)屬性,***個(gè)屬性用于選擇選項(xiàng)控件,第二個(gè)屬性用于確定選擇方式(全選還是清空)。設(shè)置兩個(gè)屬性的值如上圖,完成后label1就可以全選分類中的所有選項(xiàng)了。

簡單說來,只需要向窗體置入一個(gè)控件(Button、Label、LinkLabel、Picture),簡單設(shè)置兩個(gè)屬性,這個(gè)控件就自動具有了速選功能,不需要任何代碼。當(dāng)然得借助FastSelect組件。

 

這么神奇,是如何實(shí)現(xiàn)的呢?要從IExtenderProvider接口說起,這個(gè)接口可以向其他組件提供屬性,如上圖中的兩個(gè)屬性。有這里有兩點(diǎn)要說明一下:

  1. 向其它組件提供屬性,這個(gè)可以限定,比如僅只向Button提供。
  2. 提供屬性并不是真正給其他組件加上新的屬性,只是在WinForm設(shè)計(jì)時(shí),在PropertyGrid中顯示額外屬性(后面會詳說)。

我們來看下FastSelect是如何實(shí)現(xiàn)的: 

  1. public enum SelectionType  
  2.   {  
  3.       清空,  
  4.       反選,  
  5.       全選,  
  6.   }  
  7.  
  8.   [ProvideProperty("SelectionSource", typeof(Control))]  
  9.   [ProvideProperty("SelectionType", typeof(Control))]  
  10.   public partial class FastSelect : Component, IExtenderProvider  
  11.   {  
  12.       
  13.      public bool CanExtend(object extendee)  
  14.       {  
  15.           if (extendee == null) return false;  
  16.          if (extendee is Button || extendee is Label || extendee is PictureBox) return true;  
  17.          return false;  
  18.       }  
  19.  
  20.      [Category("速選"), Description("速選源控件"), Localizable(true)]  
  21.       public Control GetSelectionSource(Control control)  
  22.       {  
  23.           ...  
  24.       }  
  25.  
  26.      public void SetSelectionSource(Control control, Control selectionSource)  
  27.       {  
  28.           ...  
  29.       }  
  30.  
  31.  
  32.       [Category("速選"), Description("速選方式"), DefaultValue(SelectionType.清空), Localizable(true)]  
  33.       public SelectionType GetSelectionType(Control control)  
  34.       {             
  35.      }  
  36.      public void SetSelectionType(Control control, SelectionType selectionType)  
  37.      {      
  38.      ...  
  39.     }  
  40.      ...  
  41.       }  

SelectionType枚舉不必多說,我們來看FastSelect,它繼承至Component,實(shí)現(xiàn)了IExtenderProvider接口。

CanExtend是IExtenderProvider接口的***成員,它用來標(biāo)識可以給那些組件進(jìn)行擴(kuò)展,上面的代碼中我們限定了只可以給Button、Label、PictureBox進(jìn)行擴(kuò)展,也就是說其它類型的控件在屬性窗口中是看不到速選屬性的。CanExtend中沒有LinkLabel,是因?yàn)長inkLabel是Label的子類,Label有的它也會自動擁有。

Get(Set) SelectionSource、Get(Set)SelectionType有點(diǎn)類似屬性的get/set吧,只不過多了一個(gè)參數(shù)(***個(gè)參數(shù)control),傳入這個(gè)參數(shù)的是要進(jìn)行屬性擴(kuò)展的控件,還是讓我們看一下WinForm生成的代碼吧(在Form1.generated.cs中)

  1. this.fastSelect.SetSelectionSource(this.label1, this.categoriesListBox);  
  2.  this.fastSelect.SetSelectionType(this.label1, SelectionType.全選); 

對照圖三,應(yīng)該明白“提供屬性”的真正含義了吧。

我們再來看是如何實(shí)現(xiàn)選擇的,先看代碼片段:

  1. public partial class FastSelect : Component, IExtenderProvider  
  2.     {  
  3.         private Dictionary sourceControlsDict;  
  4.         private Dictionary typeDict;  
  5.  
  6.       public void SetSelectionSource(Control control, Control selectionSource)  
  7.       {  
  8.               
  9.            sourceControlsDict.Add(control, selectionSource);  
  10.              control.Click += new EventHandler(control_Click);  
  11.              
  12.        }  
  13.  
  14.        public void SetSelectionType(Control control, SelectionType selectionType)  
  15.       {  
  16.             
  17.            typeDict.Add(control, selectionType);  
  18.              
  19.         }  
  20.  
  21.         void control_Click(object sender, EventArgs e)  
  22.          {  
  23.             Control control = sender as Control;  
  24.            Control selectionSource = sourceControlsDict[control];  
  25.             SelectionType selectType = typeDict[control];  
  26.  
  27.              if (selectionSource is DataGridView)  
  28.             {  
  29.                  DataGridView dataGridView = selectionSource as DataGridView;  
  30.                  foreach (DataGridViewRow row in dataGridView.Rows)  
  31.                      row.Selected = ChangeSelected(row.Selected, selectType);  
  32.              }  
  33.               
  34.          }  
  35.    
  36.         private bool ChangeSelected(bool isSelected, SelectionType type)  
  37.          {  
  38.            if (type == SelectionType.清空) return false;  
  39.             else if (type == SelectionType.全選) return true;  
  40.            else if (type == SelectionType.反選) return !isSelected;  
  41.             else throw new NotImplementedException();  
  42.          }  
  43.            
  44.     } 

一個(gè)窗體上只需要一個(gè)FastSelect組件,但它要為其它多個(gè)組件提供屬性,我們這里使用Dictionary保存這些屬性。

設(shè)置控件SelectionSource屬性時(shí),其實(shí)是調(diào)用了SetSelectionSource方法,其中我們?yōu)榭丶粤薈lick事件,control_Click中根據(jù)不同的選項(xiàng)控件的類型(DataGridView、CheckedListBox等)和選擇類型進(jìn)行相應(yīng)的處理。這樣應(yīng)該明白了吧。

代碼比較長,就不發(fā)在文章中了,此處下載。(大部分時(shí)間花在文章上了,代碼沒太測試,可能存在問題,如發(fā)現(xiàn)請告知,謝謝了)。

原文標(biāo)題:構(gòu)建WinForm 通用速選(全選、反選、清空)組件

鏈接:http://www.cnblogs.com/ldp615/archive/2009/11/29/WinForm_FastSelect_Component.html

責(zé)任編輯:彭凡 來源: 博客園
相關(guān)推薦

2022-02-08 15:55:00

Vue組件庫Vue Demi

2010-06-13 09:15:16

WinForm窗體

2009-10-13 11:32:19

Winform假框架

2012-12-11 10:15:02

Winform開發(fā)框架

2010-08-18 09:58:33

WinFormASP.NET

2021-06-22 09:44:56

鴻蒙HarmonyOS應(yīng)用

2009-04-13 09:23:41

.NET 2.0Winform經(jīng)驗(yàn)

2024-10-24 17:13:55

WinformUI多線程

2012-07-11 15:54:59

canvas

2013-07-04 09:33:26

BGP選路

2009-11-26 14:37:37

Visual Stud

2009-10-10 14:54:44

treeView1控件

2025-02-10 00:14:00

2010-02-03 15:59:08

Android組件

2017-03-13 16:30:50

React Route構(gòu)建JavaScript

2021-04-23 16:08:08

鴻蒙HarmonyOS應(yīng)用

2010-01-07 09:53:09

Winform多線程編

2010-09-09 13:34:55

家庭網(wǎng)絡(luò)組建

2024-07-03 08:21:56

MDI窗體界面

2009-09-11 11:04:23

C# WinForm自
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號