声明:本系列非原创,因为太精彩才转载,如有侵权请通知删除,原文:http://www.cnblogs.com/wudiwushen/archive/2010/04/20/1698795.html

今天是大白话系列之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
{
}
}
}

复制代码

这样我想大家都理解了,当审批控件点击提交按钮,其实访问的就是订阅者页面的功能函数。

其实委托事件应用的场景还有很多,它就是观察者模式的提炼。

到此委托与事件讲解的大白话系列到此完毕,我非常希望大家能看了我的文章后能有点收获。

今后我会写更多的大白话系列,让抽象的东西更能让大家理解【注:因为要想些通俗的例子,所以更新的速度有点慢】

大白话系列之C#委托与事件讲解大结局的更多相关文章

  1. [转]大白话系列之C#委托与事件讲解(三)

    本文转自:http://www.cnblogs.com/wudiwushen/archive/2010/04/21/1717378.html [我希望大家在看完文章的时候,多做做练习,自己也可以想个场 ...

  2. 大白话系列之C#委托与事件讲解(一)

    从序言中,大家应该对委托和事件的重要性有点了解了吧,虽然说我们现在还是能模糊,但是从我的大白话系列中,我会把这些概念说的通俗易懂的.首先,我们还是先说说委托吧,从字面上理解,只要是中国人应该都知道这个 ...

  3. 大白话系列之C#委托与事件讲解(序言)

    声明:本系列非原创,因为太精彩才转载,如有侵权请通知删除,原文:http://www.cnblogs.com/wudiwushen/archive/2010/04/20/1698795.html 在讲 ...

  4. 大白话系列之C#委托与事件讲解(三)

    今天我接着上面的3篇文章来讲一下,为什么我们在日常的编程活动中遇到这么多sender,EventArgs e 参数:protected void Page_Load(object sender, Ev ...

  5. 大白话系列之C#委托与事件讲解(二)

    什么是事件?EVENT?点击事件?加载事件?一连串的模糊的概念冲击着我们弱小的脑袋 那我们首先来看一下比较正统的感念吧: 事件是类在发生其关注的事情时用来提供通知的一种方式. 事件的发生一般都牵扯2个 ...

  6. C#委托和事件讲解

    委托 和 事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易.它们就像是一道槛儿,过了这个槛的人,觉得真是太容易了,而没有过去的人每 ...

  7. C#委托与事件讲解(一)

    首先,我们还是先说说委托吧,从字面上理解,只要是中国人应该都知道这个意思,除非委托2个中文字不认识,举个例子,小明委托小张去买车票.     但是在我们的程序世界里,也是这么的简单吗?当然,什么是OO ...

  8. C#学习(一):委托和事件

    预备知识 在学习委托和事件之前,我们需要知道的是,很多程序都有一个共同的需求,即当一个特定的程序事件发生时,程序的其他部分可以得到该事件已经发生的通知. 而发布者/订阅者模式可以满足这种需求.简单来说 ...

  9. C# 委托和事件 与 观察者模式(发布-订阅模式)讲解 by天命

    使用面向对象的思想 用c#控制台代码模拟猫抓老鼠 我们先来分析一下猫抓老鼠的过程 1.猫叫了 2.所有老鼠听到叫声,知道是哪只猫来了 3.老鼠们逃跑,边逃边喊:"xx猫来了,快跑啊!我是老鼠 ...

随机推荐

  1. 2018-2019 2 20165210 《网络对抗技术》Exp5 MSF基础

    2018-2019 2 20165210 <网络对抗技术>Exp5 MSF基础 实验内容: 一个主动攻击实践,如ms08_067(成功); 一个针对浏览器的攻击,如ms10_046(成功) ...

  2. nginx Linux 开启自启

    编辑  /etc/init.d/nginx  添加一下内容   根据路劲修改. 添加可执行权限  chmod +x /etc/init.d/nginx 开启自启  chkconfig nginx on ...

  3. 怎么样在python 3.6里安装tensorflow?

    首先要下载python3.6: https://www.python.org/downloads/release/python-361/ 接着下载: numpy-1.13.0-cp36-none-wi ...

  4. 第23课 #error和#line使用分析

    #error的用法: 示例程序: #include <stdio.h> #ifndef __cplusplus #error This file should be processed w ...

  5. ICE:slice语言常识整理

    ICE:Slice语言(二)--源文件和词法规则:    文件命名    Slice的源文件以.ice为扩展名.   对于大小写不区分的系统(例如DOS),文件的扩展名可以大写,也可以小写,例如Cli ...

  6. centos7最小化安装后配置笔记

    一.安装wget(步骤2备用) yum install wget -y 二.切换yum源为阿里云 备份旧源: mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum ...

  7. Redis学习总结之二——Redis配置文件(Windows版)

    # Redis configuration file example # Note on units: when memory size is needed, it is possible to sp ...

  8. [Linux]Ubuntu中的System Setting

    问题 使用Ubuntu的过程中,安装搜狗输入法,卸载了系统自带的ibus.输入法搞定后,发现System Setting没有了... 原因 因为在卸载ibus等软件时,会删除一些依赖包,删除过程可能会 ...

  9. lx 与cd 的计算方法

    Candela to lux calculation with distance in meters The illuminance Ev in lux (lx) is equal to the lu ...

  10. sync or async connect redis in golang

    Head of head 在golang的整个生态里,redis client lib全部都使用多连接或者连接池.这是让人难以理解的,所以我和xiaofei一起写了一个同时支持同步和异步的redis ...