大白话系列之C#委托与事件讲解大结局
今天是大白話系列之C#委托與事件講解的大結局,也是我們最關心的,在日常的MES系統編程中到底怎樣使用這樣的利器,其實我們每天都在使用事件,一個窗體,一個按鈕都包含這事件,只是很少用到自己寫的委托和事件,說白了不知道如何下手,也不知道在什么樣的場景下應用。
用到事件的地方有很多,這次講解就MES系統開發中我們經常應用的場景。
一、通用控件場景
通用控件有很多,這里舉最常用的萬能通用分頁控件
【注:】本分頁控件,只是為了講解使用,并非真分頁控件,還是基于.net控件的分頁
我們先來看場景
我們所看到的這個分頁控件就是這次講解的主角,在日常的編程中,像這樣功能我們用的做多,所以我們必須要把它抽象出來,不能每個頁面都寫分頁邏輯吧。那我們想想到底怎樣去實現這樣的功能呢?怎樣才能讓頁面知道我們按了控件的哪個按鈕呢?這時候讓我們聯想一想委托與事件,一定要聚精會神,叮咚!有了,我們可以把這個控件想象成一個發布者,而各個頁面就想象成訂閱者,或者是觀察者,當頁面訂閱了分頁控件的事件后,自然就會相應了嘛?
有了思路,我們就開始行動吧!
第一步,我們編寫發布者代碼,也就是這個控件代碼
?
代碼
???//和我們上一講講的一樣,我們先定義訂閱者所感興趣的對象,這里我們將它抽象成Action,也就是首頁、下頁、上頁之類的動作
????public?class?PageChangeEventArgs?:?EventArgs
????{
????????private?string?action?=?string.Empty;
????????public?string?Action
????????{
????????????get
????????????{
????????????????return?this.action;
????????????}
????????????set
????????????{
????????????????this.action?=?value;
????????????}
????????}
????????public?PageChangeEventArgs()
????????{
????????}????????
????????public?PageChangeEventArgs(String?paramAction)
????????{
????????????this.Action?=?paramAction;
????????}
????}
????//發布者代碼?也就是控件代碼
????public?partial?class?UIPageControlsNavigator?:?System.Web.UI.UserControl
????{
????????//這里我們聲明一個頁面改變的委托[注:命名一定要規范]
????????public?delegate?void?PageChangeEventHandler(object?sender,?PageChangeEventArgs?e);
????????//這里我們聲明一個事件
?????????public?event?PageChangeEventHandler?PageChange;
????????//然后以個保護類型的OnPageChange方法
?????????protected?virtual?void?OnPageChange(PageChangeEventArgs?e)
????????{
????????????if?(PageChange?!=?null)
????????????{
????????????????PageChange(this,?e);
????????????}
????????}
????????//這里就是上一講中,具體的觸發函數,這里變成了一個按鈕觸發事件
?????????protected?void?lbtnFirst_Click(object?sender,?EventArgs?e)
????????{
????????????//這時候,訂閱者關心的對象e,也就是觸發的是“首頁”這個按鈕
????????????OnPageChange(new?PageChangeEventArgs("First"));
????????}
????????protected?void?lbtnPrevious_Click(object?sender,?EventArgs?e)
????????{
????????????//這時候,訂閱者關心的對象e,也就是觸發的是“下頁”這個按鈕
????????????OnPageChange(new?PageChangeEventArgs("Previous"));
????????}
????????protected?void?lbtnLast_Click(object?sender,?EventArgs?e)
????????{
????????????OnPageChange(new?PageChangeEventArgs("Last"));
????????}
????????protected?void?lbtnNext_Click(object?sender,?EventArgs?e)
????????{
????????????OnPageChange(new?PageChangeEventArgs("Next"));
????????}
????????protected?void?btnSearch_Click(object?sender,?EventArgs?e)
????????{
????????????if?(IsNumber(txtSearchPageCount.Text))
????????????{
????????????????OnPageChange(new?PageChangeEventArgs("Search"));
????????????}
????????}
????????protected?void?cmbPerPage_SelectedIndexChanged(object?sender,?EventArgs?e)
????????{
????????????OnPageChange(new?PageChangeEventArgs("PageSizeChanged"));
????????}?
????????
????????....
????????#region?public?void?BindData(GridView?myGridView,?IList?businessObjects,?PageChangeEventArgs?e)
????????///?<summary>
????????///?具體控件分頁功能實現
?????????///?</summary>
????????///?<param?name="myGridView">當前Grid控件</param>
????????///?<param?name="businessObjects">數據源</param>
????????///?<param?name="e">事件對象</param>
????????public?void?BindData(GridView?myGridView,?IList?businessObjects,?PageChangeEventArgs?e)
????????{
????????????//?計算頁面數
????????????if?(businessObjects?==?null)
????????????{
????????????????this.RowCount?=?0;
????????????}
????????????else
????????????{
????????????????this.RowCount?=?businessObjects.Count;
????????????}
????????????double?pageCount?=?(double)RowCount?/?this.PageSize;
????????????this.PageCount?=?(int)Math.Ceiling(pageCount);
????????????myGridView.DataSource?=?businessObjects;
????????????myGridView.PageSize?=?this.PageSize;
????????????switch?(e.Action)
????????????{
????????????????case?"PageLoad":
????????????????????if?(CurrentPage?>?0)
????????????????????{
????????????????????????myGridView.PageIndex?=?CurrentPage?-?1;
????????????????????}?
????????????????????break;
????????????????case?"First":
????????????????????myGridView.PageIndex?=?0;
????????????????????myGridView.EditIndex?=?-1;
????????????????????break;
????????????????case?"Previous":
????????????????????myGridView.PageIndex--;
????????????????????myGridView.EditIndex?=?-1;
????????????????????break;
????????????????case?"Next":
????????????????????myGridView.PageIndex++;
????????????????????myGridView.EditIndex?=?-1;
????????????????????break;
????????????????case?"Last":
????????????????????myGridView.PageIndex?=?this.PageCount?-?1;
????????????????????myGridView.EditIndex?=?-1;
????????????????????break;
????????????????case?"PageSizeChanged":
????????????????????myGridView.PageIndex?=?0;
????????????????????myGridView.EditIndex?=?-1;
????????????????????break;
????????????????case?"Search":
????????????????????myGridView.PageIndex?=?int.Parse(txtSearchPageCount.Text)?-?1;
????????????????????break;
????????????????case?"Refresh":
????????????????????break;
????????????????default:
????????????????????myGridView.PageIndex?=?0;
????????????????????break;
????????????}
????????????//?頁數不夠了,進行調整
????????????if?(myGridView.PageIndex?>=?this.PageCount)
????????????{
????????????????myGridView.PageIndex?=?this.PageCount?==?0???0?:?this.PageCount?-?1;
????????????}
????????????myGridView.DataBind();
????????????//?獲取按鈕的狀態
????????????this.GetButtonState(myGridView);
????????}
????????#endregion???
????}
?
?
?當然控件代碼還不值這些,我這里就列舉出我們委托事件需要的代碼:
然后我們看一下調用頁面的代碼,也就是觀察者,本例中是角色頁面RoleManage.aspx
代碼
????//角色管理頁面代碼類
????public?partial?class?RoleManage?:?BasePage
????{
????????protected?void?Page_Load(object?sender,?EventArgs?e)
????????{
????????????//在當前頁面訂閱控件的點擊事件
????????????this.myNavigator.PageChange?+=?new?PageChangeEventHandler(this.myNavigator_PageChange);
????????????if?(!Page.IsPostBack)
????????????{
????????????}
????????}
????????
????????//具體的點擊觸發函數功能,這里就是控件的分頁
????????private?void?myNavigator_PageChange(object?sender,?PageChangeEventArgs?e)
????????{
????????????this.GetAllRoles(e);
????????}
????????private?void?GetAllRoles(PageChangeEventArgs?e)
????????{
????????????try
????????????{
????????????????//角色數據源
????????????????roles?=?roleService.GetAllRoles();
????????????????//調用控件的分頁功能函數,這個封裝在分頁控件里可以,封裝在通用的類庫里也行
????????????????this.myNavigator.BindData(this.grdRole,?roles,?e);
????????????????
????????????}
????????????catch?(Exception?myException)
????????????{
????????????????return;
????????????}
????????}
}
?其實原理很簡單,當控件上按下下頁或者其它按鈕的時候,這時候因為角色管理頁面已經訂閱了這個事件,所以它會執行具體委托的那個實體函數,就這么簡單
大家了看了可能會頭大,那就自己動手試著做一下,只有做了才能真正的體會到里面的奧妙,其實和我上一講內容很相識,只是稍微有一點點的變化而已。
?
先休息一下:
名人名言:
?職業生涯:
我總覺得,職業生涯首先要關注的是自己,自己想要什么?大多數人大概沒想過這個問題,唯一的想法只是——我想要一份工作,我想要一份不錯的薪水,我知道所有人對于薪水的渴望,可是,你想每隔幾年重來一次找工作的過程么?你想每年都在這種對于工作和薪水的焦急不安中度過么?不想的話,就好好想清楚。飲鴆止渴,不能因為口渴就拼命喝毒藥。越是焦急,越是覺得自己需要一份工作,越饑不擇食,越想不清楚,越容易失敗,你的經歷越來越差,下一份工作的人看著你的簡歷就皺眉頭。于是你越喝越渴,越渴越喝,陷入惡性循環。最終只能哀嘆世事不公或者生不逢時,只能到天涯上來發泄一把,在失敗者的共鳴當中尋求一點心理平衡罷了。大多數人都有生存壓力,我也是,有生存壓力就會有很多焦慮,積極的人會從焦慮中得到動力,而消極的人則會因為焦慮而迷失方向。所有人都必須在壓力下做出選擇,這就是世道,你喜歡也罷不喜歡也罷。
?
二、業務控件場景
大家在做MES系統的時候,50%的時候是在復制黏貼,甚至有的時候有些邏輯老是復制到這里,然后復制到那里,當然起初的時候感覺很快,也不用動腦子ctrl+c,ctrl+v結束,但是到后來邏輯改了,那時候就像沒頭蒼蠅似的,早就忘了到底有多少地方用到這些邏輯,所以往往到BUG發生的時候,才恍然大悟“哦!原來這里忘了改了!”等等。我并不反對大家ctrl+c,ctrl+v,但是在享受這樣的快捷之后,騰出時間再來重構一下,看看這時候能否用是否能抽象呀?用設計模式?符不符合00的設計原則?不然你就是編10年的軟件,又能得到什么樣的提高!又扯遠了。。。
?
接下來,我們具體來看場景:
?
?這是一個工作流審批用戶控件,做MES系統的其實經常會和這個打交道,然而我們把這個邏輯封裝成一個控件,那我們在今后維護上將會減輕很多工作量
這里我只介紹這控件技術上我們用到的委托和事件的代碼
?
代碼
public?partial?class?ApprovalResults?:?System.Web.UI.UserControl
{
??//EventHandler是微軟默認的委托,在本例中我們直接就用EventHandler來表示委托,當然它的參數是Sender,e
??public?event?EventHandler?Preview;
??public?event?EventHandler?Submit;
??public?event?EventHandler?FMOK;
??public?event?EventHandler?FMProgress;
??public?event?EventHandler?FMSave;
??...
??//提交按鈕事件
??protected?void?btnSubmit_Click(object?sender,?EventArgs?e)
??{
????try
?????{
??????//觸發我們定義的事件
??????Submit(sender,?e);
?????}
?????catch?(Exception?ex)
?????{
?????...
?????}
??}
??...
}
?
然后我們到訂閱這個事件的頁面上看一下代碼
?
代碼
????public?partial?class?Preview?:?BasePage
????{
????????protected?void?Page_Load(object?sender,?EventArgs?e)
????????{
????????????...
????????????//在次頁面中訂閱審批控件的提交按鈕事件
????????????ApprovalResults1.Submit?+=?new?EventHandler(ApprovalResults1_Submit);
????????}
????????
????????//具體的提交事件功能函數
????????public?void?ApprovalResults1_Submit(object?sender,?EventArgs?e)
????????{????????????
????????????try
????????????{????????????????
????????????}
????????????catch?(Exception?ex)
????????????{???????????????
????????????}
????????????finally
????????????{?????????????
????????????}
????????}
????}
?
?
這樣我想大家都理解了,當審批控件點擊提交按鈕,其實訪問的就是訂閱者頁面的功能函數。
其實委托事件應用的場景還有很多,它就是觀察者模式的提煉。
到此委托與事件講解的大白話系列到此完畢,我非常希望大家能看了我的文章后能有點收獲。
?
from:?https://www.cnblogs.com/wudiwushen/archive/2010/04/23/1717829.html
總結
以上是生活随笔為你收集整理的大白话系列之C#委托与事件讲解大结局的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 大白话系列之C#委托与事件讲解(三)
- 下一篇: 【C#学习】delegate(委托) 和