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

来源:互联网 发布:淘宝短连接在线生成 编辑:程序博客网 时间:2024/05/17 00:18

复合控件的事件处理

本文节选自《庖丁解牛:纵向切入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属性区分单击了哪个按钮,从而决定执行哪种运算。
以上事件定义在控件内部,由子控件注册和引用事件,即相当于事件的注册和调用完全封装在控件内部,对开发人员不具有交互性,这样的事件在开发中也会常常用到。
但是在复合控件中,控件被引发一个事件时,开发人员往往也想做自己的事情,这就需要把事件交给主控件,由主控件统一暴露事件,这样开发人员在使用控件时仅需要为主控件注册事件即可,剩下的由主控件负责引发子控件的事件或执行子控件的某些功能,这里就涉及主控件与其子控件的事件衔接问题,一般分为:包含法和冒泡法两种处理方式。接下来的两节就讲解这两种方法。

原创粉丝点击