您的位置:首页 > 编程语言 > ASP

ASP.NET组件与开发之复合控件的事件处理

2009-02-16 13:20 501 查看
复合控件的事件处理
本文节选自《庖丁解牛:纵向切入ASP.NET 3.5控件和组件开发技术》一书


复合控件的事件处理按实现功能可分为三种:
(1)复合控件中子控件的内部事件处理。
(2)包含处理机制—子控件事件中调用主控件委托的事件实例。
(3)冒泡处理机制。
接下来的三节就分别说明这三种事件处理方式机制是如何实现的。
5.3.3.1 复合控件中子控件的内部事件处理
这是最简单的处理方式。复合控件中的子控件事件是单独存在的,与主控件没有任何关系,并且它们各自完成自己的功能,使用方法也很简单,就像以往直接在页面中使用事件一样。
这一节主要以CalculatorControl控件为示例演示这种类型事件的用法。首先看一下控件的运行效果图,如图5-4所示。
这是一个标准的复合控件,全部由子控件构成。其中包含两个表示运算操作数的TextBox,在下面有四个按钮分别执行加减乘除的运算。源代码如下:
/// <summary>
/// 获得本书更多内容,请看:
/// http://blog.csdn.net/ChengKing/archive/2008/08/18/2792440.aspx /// </summary>
[ToolboxData("<{0}:CalculatorControl runat=server></{0}:CalculatorControl>")]
public class CalculatorControl : CompositeControl
{
//操作数
private TextBox tb1;
private TextBox tb2;

//显示结果
private Label lb;

//操作(+-*/)
private Button bt1;
private Button bt2;
private Button bt3;
private Button bt4;

private const string ResultText = "结果列表: ";
private Unit ButtonWidth = Unit.Pixel(30);

protected override void CreateChildControls()
{
tb1 = new TextBox();
tb1.ID = "TextBox1";
this.Controls.Add(tb1);

tb2 = new TextBox();
tb2.ID = "TextBox2";
this.Controls.Add(tb2);

lb = new Label();
lb.ID = "Label1";

lb.Text = ResultText;
this.Controls.Add(lb);

bt1 = new Button();
bt1.ID = "Button1";
bt1.Width = ButtonWidth;
bt1.Text = "+";
bt1.CommandArgument = "+";
bt1.Click += new EventHandler(bt_Click);
this.Controls.Add(bt1);
bt2 = new Button();
bt2.ID = "Button2";
bt2.Width = ButtonWidth;
bt2.Text = "-";
bt2.CommandArgument = "-";
bt2.Click += new EventHandler(bt_Click);
this.Controls.Add(bt2);
bt3 = new Button();
bt3.ID = "Button3";
bt3.Width = ButtonWidth;
bt3.Text = "*";
bt3.CommandArgument = "*";
bt3.Click += new EventHandler(bt_Click);
this.Controls.Add(bt3);
bt4 = new Button();
bt4.ID = "Button4";
bt4.Width = ButtonWidth;
bt4.Text = "/";
bt4.CommandArgument = "/";
bt4.Click += new EventHandler(bt_Click);
this.Controls.Add(bt4);
}

void bt_Click(object sender, EventArgs e)
{
try
{
if (ResultText != lb.Text)
{
lb.Text = lb.Text + ", ";
}
switch (((Button)sender).CommandArgument)
{
case "+": lb.Text = lb.Text + Convert.ToString(Convert.ToInt32 (this.tb1.Text) + Convert.ToInt32(this.tb2.Text)); break;
case "-": lb.Text = lb.Text + Convert.ToString(Convert.ToInt32 (this.tb1.Text) - Convert.ToInt32(this.tb2.Text)); break;
case "*": lb.Text = lb.Text + Convert.ToString(Convert.ToInt32 (this.tb1.Text) * Convert.ToInt32(this.tb2.Text)); break;
case "/": lb.Text = lb.Text + Convert.ToString(Convert.ToInt32 (this.tb1.Text) / Convert.ToInt32(this.tb2.Text)); break;
}
}
catch
{
lb.Text = "It's is not right format, please input again.";
}
}

protected override void Render(HtmlTextWriter writer)
{
writer.AddAttribute(HtmlTextWriterAttribute.Style, "padding: 10;
background-color: #C0C0FE; font-size: 12px; width:180px;
height: 160; vertical-align: top; text-align: center;");
writer.RenderBeginTag(HtmlTextWriterTag.Div);

writer.AddAttribute(HtmlTextWriterAttribute.Border, "0");
writer.AddAttribute(HtmlTextWriterAttribute.Cellpadding, "0");
writer.AddAttribute(HtmlTextWriterAttribute.Cellspacing, "0");
writer.AddAttribute(HtmlTextWriterAttribute.Valign, "middle");
writer.RenderBeginTag(HtmlTextWriterTag.Table);

//Operating item 1
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
writer.RenderBeginTag(HtmlTextWriterTag.Td);
tb1.RenderControl(writer);
writer.RenderEndTag();
writer.RenderEndTag();

//<br>
writer.WriteBreak();

//Operating symbol
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
writer.AddAttribute(HtmlTextWriterAttribute.Align, "left");
writer.RenderBeginTag(HtmlTextWriterTag.Td);
writer.WriteEncodedText(" + - * / ");
writer.RenderEndTag();
writer.RenderEndTag();

//Operating item2
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
writer.RenderBeginTag(HtmlTextWriterTag.Td);
tb2.RenderControl(writer);
writer.RenderEndTag();
writer.RenderEndTag();

//Operating symbol
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
writer.AddAttribute(HtmlTextWriterAttribute.Align, "left");
writer.RenderBeginTag(HtmlTextWriterTag.Td);
writer.WriteEncodedText(" EQUAL ");
writer.RenderEndTag();
writer.RenderEndTag();

//The relust label
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
writer.AddAttribute(HtmlTextWriterAttribute.Align, "left");
writer.RenderBeginTag(HtmlTextWriterTag.Td);
lb.RenderControl(writer);
writer.RenderEndTag();
writer.RenderEndTag();

//Button1
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
writer.RenderBeginTag(HtmlTextWriterTag.Nobr);
writer.RenderBeginTag(HtmlTextWriterTag.Td);
bt1.RenderControl(writer);
bt2.RenderControl(writer);
bt3.RenderControl(writer);
bt4.RenderControl(writer);
writer.RenderEndTag();
writer.RenderEndTag();

writer.RenderBeginTag(HtmlTextWriterTag.Tr);
writer.AddAttribute(HtmlTextWriterAttribute.Height, "10px");
writer.RenderBeginTag(HtmlTextWriterTag.Td);
writer.RenderEndTag();
writer.RenderEndTag();

writer.RenderEndTag();

writer.RenderEndTag();
}
}
代码逻辑也比较简单。运算按钮的事件注册采用标准的事件形式:
bt1.Click += new EventHandler(bt_Click);
void bt_Click(object sender, EventArgs e)
{
//… …
}
与以往不同的是这里的事件注册不是像往常一样用在页面(Page控件)中,而是用在我们自定义的控件中。
另外,因为四个按钮的事件比较相似,所以让它们共用一个事件实例bt_Click,在事件方法体通过Button的CommandArgument属性区分单击了哪个按钮,从而决定执行哪种运算。
以上事件定义在控件内部,由子控件注册和引用事件,即相当于事件的注册和调用完全封装在控件内部,对开发人员不具有交互性,这样的事件在开发中也会常常用到。
但是在复合控件中,控件被引发一个事件时,开发人员往往也想做自己的事情,这就需要把事件交给主控件,由主控件统一暴露事件,这样开发人员在使用控件时仅需要为主控件注册事件即可,剩下的由主控件负责引发子控件的事件或执行子控件的某些功能,这里就涉及主控件与其子控件的事件衔接问题,一般分为:包含法和冒泡法两种处理方式。接下来的两节就讲解这两种方法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐