你可曾深入了解过,我们在MultiView中的View控件里面设置了按钮的CommandName之后就可以轻易的跳转到下一个视图,而不必为我们的按钮写任何事件处理程序?如果你不知道或者还不清楚,本篇带你深入了解其中的机制,以MultiView控件为例子深入。NET中的事件冒泡机制。 请看下面的内容:说到事件冒泡,我们必须要提到MultiView里面的几个静态只读的CommandName字段。
MultiView控件类有几个静态只读的CommandName字段。这些字段都是readonly类型的……
事实上他们是在静态的构造函数赋的初值。
NextViewCommandName = "NextView";PreviousViewCommandName = "PrevView";SwitchViewByIDCommandName = "SwitchViewByID";SwitchViewByIndexCommandName = "SwitchViewByIndex";我们的MultiView控件里面只能包行View控件。
不能在MultiView里面直接包含非View的服务器端控件(包括Web服务器控件和HTML服务器控件)
否则VS会报错。但是可以包含静态的HTML代码,但是要注意的是这样做没有任何意义。
因为最终生成在客户端的HTML代码中只会显示View中的内容。而且只能一次显示一个View的内容。这个View是由MultiView的ActiveViewIndex属性决定的。这个属性默认值是-1也就是不显示任何视图。
关于MultiView的命令字段CommandName.这四个命令字段主要是用在它的OnBubbleEvent()方法中的。这主要跟控件的事件冒泡有关。可以查看MultiView类的源代码。(reflector反射工具)
前面我们提到我们的按钮Button,ImageButton,LinkButton 他们有两个事件Click和Command这两个事件都是在按钮被单击的时候发生。
其中Command事件有一点特别,我们可以为按钮的两个属性: CommandName和CommandArgument指定两个值,这两个值一个是string类型的,一个是Object类型的。那么这两个值会被传入到为Command事件提供数据的类CommandEventArgs中去。
我们的按钮的Command事件处理程序类似于这样的声明:protected void Button1_Command(object sender, CommandEventArgs e)
那么,在处理事件的时候,我们为按钮类设置的属性CommandName和CommandArgument的值,都会传这里的CommandEventArgs e中的e里面来。e表示当事件发生时,事件的相关附加数据信息。
对于我们的按钮而言,它封装了当事件发生时,触发此事件的按钮的CommandName和CommandArgument的值。
我们知道我们的一般的事件处理程序都有这两个参数object sender, EventArgs e其中sender表示触发事件的控件,e表示触发此事件是的一些附加信息,e不一定是EventArgs类型,还可以是它的子类。
对于不同的事件,可能EventArgs中包含的信息不同,例如鼠标单击事件的时候,可能包含了鼠标单击时鼠标在屏幕上面的坐标等等。
那么对于上面的按钮的Command事件的事件处理程序,当我们的按钮的Command事件发生的时候那么按钮的CommandName和CommandArgument都会被传递到它的事件处理程序中的CommandEventArgs中去。我们在事件处理程序中可以进行必要的判断。那么如果页面上有多个按钮的话,我们可以共用一个事件处理程序,通过为不同的按钮设置CommandName和CommandArgument属性值,来确定每个按钮的功能。
下面回到我们的事件冒泡:NextViewCommandName = "NextView";PreviousViewCommandName = "PrevView";SwitchViewByIDCommandName = "SwitchViewByID";SwitchViewByIndexCommandName = "SwitchViewByIndex";我们的MultiView控件由上面四个静态只读字段。例如现在我们的MultiView中有3个View视图那么在每一个视图中有按钮,我们设置按钮的CommandName="NextView"我们设置MultiView默认显示的视图是第一个视图,那么当我们单击第一个View里面的按钮时,由于这个按钮的CommandName设置为NextView,所以MultiView控件会自动切换到第二个视图,而不需要我们为我们的按钮写单击事件来转到第二个视图中去。
这是MultiView控件为我们自动完成的。也就是我们只要设置View里面的按钮的CommandName属性为上面对应的NextView (下一个视图), PreView (上一个视图)
SwitchViewByID(跳转到指定id的视图) , SwitchViewByIndex(跳转到指定索引的视图)
那么当我们单击按钮的时候引发按钮的Command事件,MultiView会自动按照我们的按钮的CommandName指定的命令名执行相应的动作,而不需要我们写任何按钮的单击事件的代码。
也就是我们要做的仅仅是为按钮的CommandName属性给相应的值(这个值要是MultiView的命令名字段中的值)
为什么会发生上面的现象???
其实这里涉及到到了事件的冒泡了。我们的Control类有两个受保护的方法:protected virtual bool OnBubbleEvent(Object source,EventArgs args)
protected void RaiseBubbleEvent (Object source,EventArgs args)
那么他们的子类(也就是所有的控件类,包括Page类也是继承自Control类的)都是继承于我们的Congtrol类的。
从字面上看OnBubbleEvent表示当冒泡事件发生的时候执行。
RaiseBubbleEvent表示提升冒泡事件。
事实上Control类根本没有BubbleEvent这样的事件,也就是根本没有冒泡事件。
通过看这两个方法的源代码得知(可以用Reflector查看):protected virtual bool OnBubbleEvent(object source, EventArgs args)
{ return false;} protected void RaiseBubbleEvent(object source, EventArgs args)
{ for (Control control = this.Parent; control != null; control = control.Parent)
{ if (control.OnBubbleEvent(source, args))
{ return;}我们看到这两个方法,其中RaiseBubbleEvent是非虚方法,是不可能被重写的,