编写ASP.NET复合控件实例

// 事件冒泡

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Linq;

using System.Text;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls;

namespace ServerControl1

{

    [DefaultProperty("Text")]

    [ToolboxData("<{0}:ServerControl1 runat=server></{0}:ServerControl1>")]

    public class ServerControl1 : CompositeControl,INamingContainer

    {

        [Bindable(true)]

        [Category("Appearance")]

        [DefaultValue("")]

        [Localizable(true)]

        public string Text

        {

            get

            {

                String s = (String)ViewState["Text"];

                return ((s == null) ? "[" + this.ID + "]" : s);

            }

            set

            {

                ViewState["Text"] = value;

            }

        }

        public string Tip

        {

            get { return ViewState["aa"].ToString(); }

            set{ViewState["aa"]=value;}

        }

        TextBox tb1;

        Button btn;

        Label lb;

        protected override void CreateChildControls()

        {

            Controls.Add(new LiteralControl("<h3>第̨²一°?个?数ºy"));

             tb1 = new TextBox();

            tb1.Text = "0";

            Controls.Add(tb1);

             btn = new Button();

            btn.Text = "登Ì?录?";

            btn.CommandName = "login";

           // btn.Click += new EventHandler(btn_Click);

            Controls.Add(btn);

             lb = new Label();

            lb.Text = "aaaaaaaaa";

            Controls.Add(lb);

        }

        protected virtual void CheckBox(object source, EventArgs e)

        {

        }

        protected override bool OnBubbleEvent(object source, EventArgs e)

        {

            bool handed = false;

            if (e is CommandEventArgs )

            {

                CommandEventArgs ce = (CommandEventArgs)e;

                if (ce.CommandName=="login")

                {

                    lb.Text = "aaaaaaaa";

                    handed = true;

                }

            }

            return handed;

        }

    }

}

 

1  

 

ASP.NET中,我们可以使用CompositeControl类来派生一系统的复合控件,并将其编译到DLL中,以便以后实现控件重用,下面就以Loggin控件为例,对复合控件的开发过程进行说明。

大家如果有什么问题,请给本人发送Email[email protected]

1.        VS2010中新建一个项目,选择Web模板,在Web模板中选择ASP.NET Server Control,如下图所示:

2.        VS IDE会为我们自动添加一个ServerControl1类,将该文件名以及类名改为Login,如下图所示:

代码中第12行的“DefaultProperty”特性,是指明当该控件被拖放到设计器中,并且被选中时,被控件的默认具备高亮提示的属性是Text属性。

13行的“ToolboxData”特性,是指明当该控件被拖放到VS的设计器中,在HTML代码视图中所显示的文本内容,为了让该内容中显示的控件名和该控件类的类名相同,将该行代码做如下修改:

[ToolboxData("<{0}:Loggin runat=server>")]

其中是占位符,在最终拖放在设计器中时,会被该控件的命名空间所代替。

16行的Bindable特性,是指明该属性是否可以在绑定设计器可见,true为可见,False为不可见,但是这个时我们仍然可以在ASPX页面里直接将该属性与绑定表达式进行关联,比较手动输入Eval()语句。比如说,我们将该控件放在了一个GridView的模板列里,如果想让该属性绑定到“CustomerID”字段上,如果设置Bindable(true),那么我们可以绑定设计器看到该Text属性,如下图所示:

如果将其设置为false,那么我们就只在ASPX页面中手动编写Eval(CustomerID)表达示。

17行的Category特性,是指将该Text属性应该位于属性窗口的哪一个分组里。上面代码中设置的Category的值是“Appearence,这就意味着,将该控件拖放到VS的设计器中以后,并查看该控件的属性,如果属性窗口的显示排列方式是按分类方式排列,些时,Text属性就会出现在Appearance分组栏中,如下图所示:

18行“DefaultValue”特性用来设置该属性的默认值。

19行“Localizable特性,是该属性是否可以自动查找本地化资源文件以进行本地化。

3.        前面对代码中的特性类进行了简要的分析,下面我们要对代码进行修改。首先,要想将我们的Login控件变为复合控件,就要将该控件类的基类修改为CompositeControl类,为复合控件中添加子控件,主要是通过重写基类的CreateChildControl方法来实现的,下面代码实现为Login控件添加了控件的功能:

    ///  

    /// 用来输入用户名的文本框

    ///  

    private TextBox tbxUserName;

    ///

    /// 用来输入密码的文本框

    ///  

    private TextBox tbxPassword;

    ///

    /// 用来提交的确认按钮

    ///  

    private Button bt;

    protected override void CreateChildControls()

    {

        //清空原有的子控件

        this.Controls.Clear();

        //初始化新的子控件

        this.tbxUserName = new TextBox();

        this.tbxPassword = new TextBox();

        this.tbxPassword.TextMode = TextBoxMode.Password;

        this.bt = new Button();

        //注册Button的Click事件

        this.bt.Click += new EventHandler(bt_Click);

        bt.Text = "log in";

 

        //以Table的方式为这些子控件进行布局

        Table table = new Table();

        TableCell cell00 = new TableCell();

        cell00.Text = "user name:";

        TableCell cell01 = new TableCell();

        cell01.Controls.Add(this.tbxUserName);

 

        TableRow row0 = new TableRow();

        row0.Cells.Add(cell00);

        row0.Cells.Add(cell01);

 

        TableCell cell10 = new TableCell();

        cell10.Text = "password:";

        TableCell cell11 = new TableCell();

        cell11.Controls.Add(this.tbxPassword);

 

        TableRow row1 = new TableRow();

        row1.Cells.Add(cell10);

        row1.Cells.Add(cell11);

 

 

        TableCell cell20 = new TableCell();

        cell20.ColumnSpan = 2;

        cell20.Controls.Add(this.bt);

        TableRow row2 = new TableRow();

        row2.Cells.Add(cell20);

 

        table.Rows.Add(row0);

        table.Rows.Add(row1);

        table.Rows.Add(row2);

 

        //将新建立的Table添加到子控件的集合中

        this.Controls.Add(table);

        //通知该控件所以的子控件已经创建完毕

        this.ChildControlsCreated = true;

 

 

        base.CreateChildControls();

    }

 

    //当用户登录验证完毕之后触发

    public event EventHandler UserLoggedIn;

 

    void bt_Click(object sender, EventArgs e)

    {

        var conStr = ConfigurationManager.ConnectionStrings["testConnectionString"].ConnectionString;

        using (SqlConnection con = new SqlConnection(conStr))

        {

            var cmd = con.CreateCommand();

            cmd.CommandText = "select count(*) from users where uid=@uid and pwd=@pwd";

            cmd.Parameters.Add("@uid", SqlDbType.NVarChar, 50).Value = this.tbxUserName.Text;

            cmd.Parameters.Add("@pwd", SqlDbType.NVarChar, 50).Value = this.tbxPassword.Text;

            con.Open();

            int count = (int)cmd.ExecuteScalar();

            if (this.UserLoggedIn != null)

            {

                bool result = count == 0 ? false : true;

                this.UserLoggedIn(this, new UserLoggedInEventArgs() { Validated = result });

            }

        }

}

4.        验证该控件的功能

首先,在解决方案中添加一个网站,然后编译前面的控件库,此时,我们会在工具箱里看到刚才编写的控件,如下图所示:

将其拖动到设计器,如下图所示:

在该控件中我们所添加的自定义事件如下图所示:

5.        由些看来,编写基本的自定义复合控件还是比较简单的,但是我在编写代码的同时,也会发现,由于没有设计器辅助支持,自定义复合控件的界面是一件比较麻烦的事情,程序员只能凭借自己的直观记忆和美工指定的数值化参数来设计。

          6. 该控件类的完整代码如下所示:

001 using System;
002 using System.Collections.Generic;
003 using System.ComponentModel;
004 using System.Linq;
005 using System.Text;
006 using System.Web;
007 using System.Web.UI;
008 using System.Web.UI.WebControls;
009 using System.Configuration;
010 using System.Data.SqlClient;
011 using System.Data;
012  
013 namespace MyControlLib
014 {
015     [DefaultProperty("Text")]
016     [ToolboxData("<{0}:Loggin runat=server></{0}:Loggin>")]
017     public class Loggin : CompositeControl
018     {
019         [Description("this is the event")]
020         public event EventHandler<UserLoggedInEventArgs> UserLoggedIn;
021  
022  
023         /// <summary>
024         /// 用来输入用户名的文本框
025         /// </summary>
026         private TextBox tbxUserName;
027         /// <summary>
028         /// 用来输入密码的文本框
029         /// </summary>
030         private TextBox tbxPassword;
031         /// <summary>
032         /// 用来提交的确认按钮
033         /// </summary>
034         private Button bt;
035         protected override void CreateChildControls()
036         {
037             //清空原有的子控件
038             this.Controls.Clear();
039             //初始化新的子控件
040             this.tbxUserName = new TextBox();
041             this.tbxPassword = new TextBox();
042             this.tbxPassword.TextMode = TextBoxMode.Password;
043             this.bt = new Button();
044             //注册Button的Click事件
045             this.bt.Click += new EventHandler(bt_Click);
046             bt.Text = "log in";
047  
048             //以Table的方式为这些子控件进行布局
049             Table table = new Table();
050             TableCell cell00 = new TableCell();
051             cell00.Text = "user name:";
052             TableCell cell01 = new TableCell();
053             cell01.Controls.Add(this.tbxUserName);
054  
055             TableRow row0 = new TableRow();
056             row0.Cells.Add(cell00);
057             row0.Cells.Add(cell01);
058  
059             TableCell cell10 = new TableCell();
060             cell10.Text = "password:";
061             TableCell cell11 = new TableCell();
062             cell11.Controls.Add(this.tbxPassword);
063  
064             TableRow row1 = new TableRow();
065             row1.Cells.Add(cell10);
066             row1.Cells.Add(cell11);
067  
068  
069             TableCell cell20 = new TableCell();
070             cell20.ColumnSpan = 2;
071             cell20.Controls.Add(this.bt);
072             TableRow row2 = new TableRow();
073             row2.Cells.Add(cell20);
074  
075             table.Rows.Add(row0);
076             table.Rows.Add(row1);
077             table.Rows.Add(row2);
078  
079             //将新建立的Table添加到子控件的集合中
080             this.Controls.Add(table);
081             //通知该控件所以的子控件已经创建完毕
082             this.ChildControlsCreated = true;
083  
084  
085             base.CreateChildControls();
086         }
087  
088         void bt_Click(object sender, EventArgs e)
089         {
090             var conStr = ConfigurationManager.ConnectionStrings["testConnectionString"].ConnectionString;
091             using (SqlConnection con = new SqlConnection(conStr))
092             {
093                 var cmd = con.CreateCommand();
094                 cmd.CommandText = "select count(*) from users where uid=@uid and pwd=@pwd";
095                 cmd.Parameters.Add("@uid", SqlDbType.NVarChar, 50).Value = this.tbxUserName.Text;
096                 cmd.Parameters.Add("@pwd", SqlDbType.NVarChar, 50).Value = this.tbxPassword.Text;
097                 con.Open();
098                 int count = (int)cmd.ExecuteScalar();
099                 if (this.UserLoggedIn != null)
100                 {
101                     bool result = count == 0 ? false : true;
102                     this.UserLoggedIn(this, new UserLoggedInEventArgs() { Validated = result });
103                 }
104             }
105         }
106     }
107 }

你可能感兴趣的:(asp.net)