C# 事件的使用案例

Wesley13
• 阅读 704

事件的使用案列

一、案例背景

在写一个询价报价的Winfrom程序时,程序首页FORM(form名为FrmEnquiry)显示的询价记录和报价记录,

询价记录如下图:

 C# 事件的使用案例

在用户点击新增询价记录后弹出询价记录编辑FORM(form名为FrmEnquiryEdit),界面如下图:

 C# 事件的使用案例

案例需求:用户在编辑页面(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)需要通知主界面更新显示出刚刚新增询价记录)

二、总结

  总结一下事件的使用步骤如下(步骤无需完全按照下面的来,各步骤代码可按自己习惯的顺序编写):

  1. 如果事件需要传递自定义数据则定义事件传递数据类。
  2. 定义包装收到事件后的处理方法的委托类,该委托要与事件处理方法的返回值类型和参数个数及类型完全一致,(委托声明的返回值类型、参数与其代表的方法要完全一致。)
  3. 在事件发布类中定义一个事件(既用2中的委托类声明一个类型为委托的公有事件属性,如:public event 委托类 事件属性名)。
  4. 在事件订阅类中编写收到事件后的处理方法代码(事件处理方法的返回值类型和参数个数及类型要与委托完全一致)。
  5. 在发布事件的类中自己想要触发事件的地方发布事件
  6. 在接收的事件类中订阅事件

小见,案例程序接收的事件类在实例化事件发布后就把事件跟处理方法绑定了,事件的处理方法列表中就不再为null,所以触发事件时及可找到调用的方法。在接收的事件类的不同地方绑定事件处理方法可以有很多变化。

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
2年前
java将前端的json数组字符串转换为列表
记录下在前端通过ajax提交了一个json数组的字符串,在后端如何转换为列表。前端数据转化与请求varcontracts{id:'1',name:'yanggb合同1'},{id:'2',name:'yanggb合同2'},{id:'3',name:'yang
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Easter79 Easter79
2年前
sql注入
反引号是个比较特别的字符,下面记录下怎么利用0x00SQL注入反引号可利用在分隔符及注释作用,不过使用范围只于表名、数据库名、字段名、起别名这些场景,下面具体说下1)表名payload:select\from\users\whereuser\_id1limit0,1;!(https://o
Stella981 Stella981
2年前
Modbus功能码及错误码说明
有效功能码说明(十进制)功能码说明01读取线圈状态02读取输入状态03读取保持寄存器04读取输入寄存器05强置单线圈06预置单寄存器07读取异常状态08回送诊断校验09编程(只用于484)10控询11读取事件计数12读取通信事件记录13编程
Stella981 Stella981
2年前
GitHub 上有哪些适合新手跟进的优质项目?
!(https://oscimg.oschina.net/oscnet/011f28e3bc332010e1442e6c00ed344805d.jpg)点击上方“迈微电子研发社”,选择“星标★”公众号重磅干货,第一时间送达!(https://oscimg.oschina.net/oscnet/cd44ba75f
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
为什么mysql不推荐使用雪花ID作为主键
作者:毛辰飞背景在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建议采用uuid,使用uuid究