提到 User Control, 大家都很熟悉。一般多个页面要用到重复的控件元素时,可以将这些控件封装到User Control里,以提高系统的可维护性和扩展性。为了提高控件和页面的松散耦合度,当页面和User Control进行交互时,可以使用自定义事件。下面我用具体项目中应用的User Control,简单给大家介绍一下,如何在User Control中自定义事件,以及在页面里如何响应User Control的事件。
1. 封装User Control的原因
我做的这个控件有一个ListBox,旁边有两个按钮,一个是Add按钮,用来添加用户,一个是Remove按钮,用来删除用户。用户的名称显示在ListBox之中。在添加和删除的时候本控件要做出验证,比如不能添加重复的用户,删除必须至少剩下一人。因此控件在进行操作时需要提供验证反馈信息,信息要显示在它所在的页面里。由于有多个页面需要这样的功能,所以我要将这个功能做成一个User Control。而我之所以要自定义的事件是因为在操作控件失败时,能够显示User Control反馈的验证信息,而且可以将User Control的反馈信息显示在想要显示的地方。
2. 自定义事件
定义事件很简单,在定义之前,我们要考虑一下事件所提供的参数是否要带一些个相关信息?这样可以分为两种情况:
1> 不带相关信息参数的事件
如果是这种情况,那更简单,我们可以直接用.NET已经定义好的事件,在User Control里这样定义:
public event EventHandler HandlerName;
然后在要激发事件的地方这样写:
if(HandlerName!= null)
{
HandlerName (this, e);
}
需要注意的是,我们要事先检查一下HandlerName是否为Null,如果事件没有被订阅的话,没有必要激发事件。
1> 带有相关信息参数的事件
显然我做的User Control事件参数是要带信息的,这个信息就是反馈文本。
我们需要写一个自定义事件参数类,继承自EventArgs。
我写了个UserListEventArgs类,添加了一个Message属性,用来填充反馈信息。
好,我们在User Control里先定义一个公共代理:
public delegate void MessageNotifiedEventHandler(Object sender, Business.UserListEventArgs e);
注意,其签名的第二个参数是我定义的参数类。
然后定义一个公共的event成员变量:
public event MessageNotifiedEventHandler MessageNotified;
好,在我们要反馈信息的地方,比如添加用户重复了,需要这样激发事件:
string message = string.Format("The user {0} already existed.", hidUserName.Value);
if (MessageNotified != null)
{
Business.UserListEventArgs args = new Business.UserListEventArgs();
args.Message = message;
MessageNotified(this, args);
}
注意要检查事件是否被订阅了。
由于.NET Framework2.0引入了泛型,我们可以采用EventHandler类型的一般版本:EventHandler<T>,这里可以这样写:
两种定义是等效的。
3. 订阅事件
我们可以把封装好的User Control拖到相应的页面里,然后在这个页面里响应User Control的事件。
首先我们要订阅此事件,在哪里订阅好呢?建议在Page的Page_Init事件里进行订阅,如下:
protected void Page_Init(object sender, EventArgs e)
{
UserList1.MessageNotified += new ArchiveSystem.Components.UserList.MessageNotifiedEventHandler(UserList1_MessageNotified);
}
其中UserList1是本页面User Control的ID。
我们在相应的响应事件中就可以任意处理其所带过来的反馈信息了:
private void UserList1_MessageNotified(object sender, UserListEventArgs e)
{
lblError.Text = e.Message;
}
其中lblError是本页面一个统一的显示反馈信息的标签。
4. 其它
当然了我们需要访问这个控件的人员信息,那么你觉得应当把ListBox(封装到公共属性中)直接暴露给外界好吗?我觉得外界不必直接操作这个ListBox。我封装了一个Items公共属性来让外界访问人员信息,并且暴露了一个Public的BindData(string users)函数来让外界初始化这个User Control人员信息。
希望我写的这篇随便能给大家带来些帮助。