事件的使用案列
一、案例背景
在寫一個詢價報價的Winfrom程序時,程序首頁FORM(form名為FrmEnquiry)顯示的詢價記錄和報價記錄,
詢價記錄如下圖:
在用戶點擊新增詢價記錄后彈出詢價記錄編輯FORM(form名為FrmEnquiryEdit),界面如下圖:
案例需求:用戶在編輯頁面(FrmEnquiryEdit)中編輯完詢價記錄后在點擊保存新增詢價記錄按鈕后編輯界面(FrmEnquiryEdit)需要通知主界面更新顯示出剛剛新增詢價記錄。
應用自定義事件,在用戶點擊保存新增詢價記錄按鈕后觸發事件通知主界面更新 以實現案例需求。代碼實現步驟如下:
1、 首先定義一個用於在事件中傳遞數據用的事件數據類,代碼如下:
public class EqDocumentSavedEventArgs : EventArgs { private EnquiryDocument _enquiryDocument; /// <summary> /// 編輯頁面使用該屬性傳遞新增編輯完成並保存后的詢價記錄 /// </summary> public EnquiryDocument EnquiryDocument { get => _enquiryDocument; }
public EqDocumentSavedEventArgs(EnquiryDocument enquiry) { _enquiryDocument = enquiry; } }
注:其中EnquiryDocument為我需要通過事件傳遞的詢價記錄實體類
2、 定義一個事件的委托,代碼如下:
public delegate void EqDocumentsChangedEventHandler(object sender, EqDocumentSavedEventArgs e);
委托也是一個類,可以定義在命名空間中,跟其他類同級,案例代碼層次結構如下:
namespace xunjia1.Views { public delegate void EqDocumentsChangedEventHandler(object sender, EqDocumentSavedEventArgs e); public partial class FrmEnquiry : DevExpress.XtraEditors.XtraForm { … … } public class EqDocumentSavedEventArgs : EventArgs { … … } … … }
3、 在編輯詢價記錄界面(FrmEnquiryEdit)中用2步中定義的委托聲明事件,代碼及層次結構如下:
namespace xunjia1.Views { public partial class FrmEnquiryEdit : DevExpress.XtraEditors.XtraForm { … … public event EqDocumentsChangedEventHandler EqDocumentSaved; … … } }
4、 在主頁面(FrmEnquiry)中編寫收到事件后的處理方法(暨更新主頁面),代碼及層次結構如下:
public partial class FrmEnquiry : DevExpress.XtraEditors.XtraForm { … … ……
private void frmEnquiryEdit_EqDocumentSaved(object sender,EqDocumentSavedEventArgs eq) { this.enquiryDocuments.Add(eq.EnquiryDocument); this.gridControl2.RefreshDataSource(); } … … ……
}
5、在編輯頁面(FrmEnquiryEdit)保存新增詢價記錄按鈕方法中添加發布事件代碼,代碼及層次結構如下:
public partial class FrmEnquiryEdit : DevExpress.XtraEditors.XtraForm { … … private void sBtnSaveEQDoc_Click(object sender, EventArgs e) { … … //發布事件通知主界面更新數據 if (EqDocumentSaved != null) { EqDocumentSavedEventArgs eq = new EqDocumentSavedEventArgs(enquiryDocument); EqDocumentSaved(this, eq); } … … } }
注:如果沒有任何客戶將委托與該事件掛鈎,該字段將為空;否則該字段引用應在調用該事件時調用的委托。因此,調用事件時通常先檢查是否為空,然后再調用事件。
6、在主頁面(FrmEnquiry)中新增詢價記錄按鈕方法中訂閱新增詢價記錄事件、代碼如下:
public partial class FrmEnquiry : DevExpress.XtraEditors.XtraForm {
… …
private void sBtnNewEnquiry_Click(object sender, EventArgs e) { …… FrmEnquiryEdit frmEnquiryEdit = new FrmEnquiryEdit(enquiryDocument,true); //先移除事件綁定的所有方法(如果有) frmEnquiryEdit.ClearEqDocChangedEvent(); //添加新綁定,訂閱事件 frmEnquiryEdit.EqDocumentSaved += new EqDocumentsChangedEventHandler(frmEnquiryEdit_EqDocumentSaved);
frmEnquiryEdit.Show(); ……
}
… …
}
其中frmEnquiryEdit.ClearEqDocChangedEvent();先清除事件綁定的所有的方法的目的是為了防止事件處理方法被多次調用,其實現代碼如下
public partial class FrmEnquiryEdit : DevExpress.XtraEditors.XtraForm { … …
public void ClearEqDocChangedEvent() { if (EqDocumentSaved != null) { EqDocumentSaved.GetInvocationList().ToList().ForEach(p => EqDocumentSaved -= p as EqDocumentsChangedEventHandler); } } … … }
至此,案例需求實現完成(用戶在編輯頁面(FrmEnquiryEdit)中編輯完詢價記錄后在點擊保存新增詢價記錄按鈕后編輯界面(FrmEnquiryEdit)需要通知主界面更新顯示出剛剛新增詢價記錄)
二、總結
總結一下事件的使用步驟如下(步驟無需完全按照下面的來,各步驟代碼可按自己習慣的順序編寫):
- 如果事件需要傳遞自定義數據則定義事件傳遞數據類。
- 定義包裝收到事件后的處理方法的委托類,該委托要與事件處理方法的返回值類型和參數個數及類型完全一致,(委托聲明的返回值類型、參數與其代表的方法要完全一致。)
- 在事件發布類中定義一個事件(既用2中的委托類聲明一個類型為委托的公有事件屬性,如:public event 委托類 事件屬性名)。
- 在事件訂閱類中編寫收到事件后的處理方法代碼(事件處理方法的返回值類型和參數個數及類型要與委托完全一致)。
- 在發布事件的類中自己想要觸發事件的地方發布事件
- 在接收的事件類中訂閱事件
小見,案例程序接收的事件類在實例化事件發布后就把事件跟處理方法綁定了,事件的處理方法列表中就不再為null,所以觸發事件時及可找到調用的方法。在接收的事件類的不同地方綁定事件處理方法可以有很多變化。