上一篇写了控件样式的一些基础的东西,接着我们继续讨论asp.net控件开发的一些东西.
这次我们要讨论的是复合控件.本文无法一步到位完整介绍,因为讨论的篇幅比较大,所以分两次写,这次就先讲些基本概念吧,剩着的下次写.
好象复合控件网上已经有很多教程了,相信大家也看过很多.如果看过的朋友就当我再废话一便,没看过的朋友希望能给你带来帮助.
1.复合控件概念
复合控件跟用户控件有很多相似点,最大不同就是用户控件后缀为ascx,而复合控件编译后则为dll文件,还可以分发给大家使用,另外其他不同点还请参考MSDN吧,说白了,复合控件灵活性更大.
2.复合控件的呈现
(1)一般控件的呈现
从第一篇到第六篇为止,我们用以呈现控件的方法介绍过的有Render方法和RenderContents方法.回顾一下吧,看以下其中的一小段代码.
示例一
 public override void Render(HtmlTextWriter writer)
          public override void Render(HtmlTextWriter writer)
 {
      {
 
  ..
..
 writer.RenderBeginTag(HtmlTextWriterTag.Td);
              writer.RenderBeginTag(HtmlTextWriterTag.Td);
 writer.AddAttribute(HtmlTextWriterAttribute.Name, "CreditCardNo");
          writer.AddAttribute(HtmlTextWriterAttribute.Name, "CreditCardNo");
 writer.AddAttribute(HtmlTextWriterAttribute.Id, "CreditCardNo");
          writer.AddAttribute(HtmlTextWriterAttribute.Id, "CreditCardNo");
 writer.AddAttribute(HtmlTextWriterAttribute.Type, "text");
          writer.AddAttribute(HtmlTextWriterAttribute.Type, "text");
 writer.RenderBeginTag(HtmlTextWriterTag.Input);
          writer.RenderBeginTag(HtmlTextWriterTag.Input);
 writer.RenderEndTag();
          writer.RenderEndTag();
 writer.RenderEndTag();
          writer.RenderEndTag();
 
          

 }
}
以前我们所做的控件都是上面这样的写法.我们可以认为在Render方法实现了以下两个功能.
一.标签布局(如td标签,让控件呈现的好看点-_-)
二.呈现的标签(如input标签)
(2)复合控件的呈现方法
我们知道asp.net控件库里面已经提供给了我们像TextBox这样的控件了,就如组装电脑一下,你可以组装.net提供你现有的控件,然后重新拼凑成一个新的控件,这样便成了复合控件.但其呈现方法却又不同.
复合控件是以包含子控件的形式呈现的,具体的呈现交给子控件自己去做,因为子控件自身都已经实现了其呈现方法(每个控件都继承自Control类).假设你还不明白就看下面的图吧.
LabelTextBox1为复合控件,LabelTextBox2则不是.两者的呈现方式是不同的.具体实现方法请看下文

3.完成基本复合控件基本呈现
(1)首先你要熟悉以下的属性和方法
Control.CreateChildControls 方法用于创建子控件
Control.EnsureChildControls 方法用于确认是否已创建子控件,如果未创建完成的话则调用CreateChildControls 方法创建子控件
Control.ChildControlsCreated 属性 获取一个值,是否已创建子控件
(2)了解并实现INamingContainer接口
用户控件UserControl类则继承了INamingContainer接口,确包保子控件具有唯一的ID名称,那复合控件也需要实现这个接口达到一样的目的,这个是值得注意的地方.
复合控件以类撰写的方法来添加控件即CreateChildControls 方法,而非在Render方法中以下面方式实现
 writer.RenderBeginTag(HtmlTextWriterTag.Input);
writer.RenderBeginTag(HtmlTextWriterTag.Input);

在复合控件里Render方法的作用只是为我们提供布局的需要
下面看一个完成的代码,以微软的示例为例子.一个登录控件.
先看效果如下

再来看看代码吧,其实以下代码并不复杂.只不过属性多一点而已.看下面步骤
先定义控件类很简单.
然后定义几个公开的属性,注意每个属性都有一个EnsureChildControls 方法,因为返回的都是控件的属性,而我们又无法判断控件是否已经创建,所以须用此方法确保已创建控件,然后才可以使用其属性.
再通过类撰写方法CreateChildControls来添加子控件.
最后在Render方法实现布局以及用控件的RenderControl方法呈现自身标签内容,最后还要注意Render方法中的AddAttributesToRender方法,以前已经解释过这个方法的用处了,不调用此方法就无福享用WebControl类提供给你诸多样式属性了
以下注意的地方均以红字标出.说了一大堆了,看看下面代码,你明白了没?
示例二

 public class CompositeLogin : WebControl, INamingContainer
 public class CompositeLogin : WebControl, INamingContainer
 {
    {

 private Button _button;
        private Button _button;
 private TextBox _nameTextBox;
        private TextBox _nameTextBox;
 private Label _nameLabel;
        private Label _nameLabel;
 private TextBox _passwordTextBox;
        private TextBox _passwordTextBox;
 private Label _passwordLabel;
        private Label _passwordLabel;
 private RequiredFieldValidator _nameValidator;
        private RequiredFieldValidator _nameValidator;
 private RequiredFieldValidator _passwordValidator;
        private RequiredFieldValidator _passwordValidator;

 #region 属性
        #region 属性
 [
        [
 Bindable(true),
        Bindable(true),
 Category("Appearance"),
        Category("Appearance"),
 DefaultValue(""),
        DefaultValue(""),
 Description("按钮文本")
        Description("按钮文本")
 ]
        ]
 public string ButtonText
        public string ButtonText
 {
        {
 get
            get
 {
            {
 EnsureChildControls();
                EnsureChildControls();
 return _button.Text;
                return _button.Text;
 }
            }
 set
            set
 {
            {
 EnsureChildControls();
                EnsureChildControls();
 _button.Text = value;
                _button.Text = value;
 }
            }
 }
        }

 [
        [
 Bindable(true),
        Bindable(true),
 Category("Default"),
        Category("Default"),
 DefaultValue(""),
        DefaultValue(""),
 Description("姓名")
        Description("姓名")
 ]
        ]
 public string Name
        public string Name
 {
        {
 get
            get
 {
            {
 EnsureChildControls();
                EnsureChildControls();
 return _nameTextBox.Text;
                return _nameTextBox.Text;
 }
            }
 set
            set
 {
            {
 EnsureChildControls();
                EnsureChildControls();
 _nameTextBox.Text = value;
                _nameTextBox.Text = value;
 }
            }
 }
        }

 [
        [
 Bindable(true),
        Bindable(true),
 Category("Appearance"),
        Category("Appearance"),
 DefaultValue(""),
        DefaultValue(""),
 Description(
        Description(
 "必须输入姓名")
            "必须输入姓名")
 ]
        ]
 public string NameErrorMessage
        public string NameErrorMessage
 {
        {
 get
            get
 {
            {
 EnsureChildControls();
                EnsureChildControls();
 return _nameValidator.ErrorMessage;
                return _nameValidator.ErrorMessage;
 }
            }
 set
            set
 {
            {
 EnsureChildControls();
                EnsureChildControls();
 _nameValidator.ErrorMessage = value;
                _nameValidator.ErrorMessage = value;
 _nameValidator.ToolTip = value;
                _nameValidator.ToolTip = value;
 }
            }
 }
        }

 [
        [
 Bindable(true),
        Bindable(true),
 Category("Apperance"),
        Category("Apperance"),
 DefaultValue(""),
        DefaultValue(""),
 Description("姓名标签")
        Description("姓名标签")
 ]
        ]
 public string NameLabel
        public string NameLabel
 {
        {
 get
            get
 {
            {
 EnsureChildControls();
                EnsureChildControls();
 return _nameLabel.Text;
                return _nameLabel.Text;
 }
            }
 set
            set
 {
            {
 EnsureChildControls();
                EnsureChildControls();
 _nameLabel.Text = value;
                _nameLabel.Text = value;

 }
            }
 }
        }

 [
        [
 Browsable(false),
        Browsable(false),
 DesignerSerializationVisibility(
        DesignerSerializationVisibility(
 DesignerSerializationVisibility.Hidden)
            DesignerSerializationVisibility.Hidden)
 ]
        ]
 public string Password
        public string Password
 {
        {
 get
            get
 {
            {
 EnsureChildControls();
                EnsureChildControls();
 return _passwordTextBox.Text;
                return _passwordTextBox.Text;
 }
            }
 }
        }

 [
        [
 Bindable(true),
        Bindable(true),
 Category("Appearance"),
        Category("Appearance"),
 DefaultValue(""),
        DefaultValue(""),
 Description(
        Description(
 "必须输入密码")
            "必须输入密码")
 ]
        ]
 public string PasswordErrorMessage
        public string PasswordErrorMessage
 {
        {
 get
            get
 {
            {
 EnsureChildControls();
                EnsureChildControls();
 return _passwordValidator.ErrorMessage;
                return _passwordValidator.ErrorMessage;
 }
            }
 set
            set
 {
            {
 EnsureChildControls();
                EnsureChildControls();
 _passwordValidator.ErrorMessage = value;
                _passwordValidator.ErrorMessage = value;
 _passwordValidator.ToolTip = value;
                _passwordValidator.ToolTip = value;
 }
            }
 }
        }

 [
        [
 Bindable(true),
        Bindable(true),
 Category("Appearance"),
        Category("Appearance"),
 DefaultValue(""),
        DefaultValue(""),
 Description("密码标签")
        Description("密码标签")
 ]
        ]
 public string PasswordLabel
        public string PasswordLabel
 {
        {
 get
            get
 {
            {
 EnsureChildControls();
                EnsureChildControls();
 return _passwordLabel.Text;
                return _passwordLabel.Text;
 }
            }
 set
            set
 {
            {
 EnsureChildControls();
                EnsureChildControls();
 _passwordLabel.Text = value;
                _passwordLabel.Text = value;

 }
            }
 }
        }
 #endregion Properties delegated to child controls
        #endregion Properties delegated to child controls

 #region 方法
        #region 方法
 //撰写
        //撰写
 protected override void CreateChildControls()
        protected override void CreateChildControls()
 {
        {
 Controls.Clear();
            Controls.Clear();

 _nameLabel = new Label();
            _nameLabel = new Label();

 _nameTextBox = new TextBox();
            _nameTextBox = new TextBox();
 _nameTextBox.ID = "nameTextBox";
            _nameTextBox.ID = "nameTextBox";

 _nameValidator = new RequiredFieldValidator();
            _nameValidator = new RequiredFieldValidator();
 _nameValidator.ID = "validator1";
            _nameValidator.ID = "validator1";
 _nameValidator.ControlToValidate = _nameTextBox.ID;
            _nameValidator.ControlToValidate = _nameTextBox.ID;
 _nameValidator.Text = "*";
            _nameValidator.Text = "*";
 _nameValidator.Display = ValidatorDisplay.Static;
            _nameValidator.Display = ValidatorDisplay.Static;

 _passwordLabel = new Label();
            _passwordLabel = new Label();

 _passwordTextBox = new TextBox();
            _passwordTextBox = new TextBox();
 _passwordTextBox.TextMode = TextBoxMode.Password;
            _passwordTextBox.TextMode = TextBoxMode.Password;
 _passwordTextBox.ID = "passwordTextBox";
            _passwordTextBox.ID = "passwordTextBox";

 _passwordValidator = new RequiredFieldValidator();
            _passwordValidator = new RequiredFieldValidator();
 _passwordValidator.ID = "validator2";
            _passwordValidator.ID = "validator2";
 _passwordValidator.ControlToValidate = _passwordTextBox.ID;
            _passwordValidator.ControlToValidate = _passwordTextBox.ID;
 _passwordValidator.Text = "*";
            _passwordValidator.Text = "*";
 _passwordValidator.Display = ValidatorDisplay.Static;
            _passwordValidator.Display = ValidatorDisplay.Static;

 _button = new Button();
            _button = new Button();
 _button.ID = "button1";
            _button.ID = "button1";

 this.Controls.Add(_nameLabel);
            this.Controls.Add(_nameLabel);
 this.Controls.Add(_nameTextBox);
            this.Controls.Add(_nameTextBox);
 this.Controls.Add(_nameValidator);
            this.Controls.Add(_nameValidator);
 this.Controls.Add(_passwordLabel);
            this.Controls.Add(_passwordLabel);
 this.Controls.Add(_passwordTextBox);
            this.Controls.Add(_passwordTextBox);
 this.Controls.Add(_passwordValidator);
            this.Controls.Add(_passwordValidator);
 this.Controls.Add(_button);
            this.Controls.Add(_button);
 }
        }

 //布局
        //布局
 protected override void Render(HtmlTextWriter writer)
        protected override void Render(HtmlTextWriter writer)
 {
        {
 AddAttributesToRender(writer);
            AddAttributesToRender(writer);

 writer.AddAttribute(HtmlTextWriterAttribute.Cellpadding,
            writer.AddAttribute(HtmlTextWriterAttribute.Cellpadding,
 "1", false);
                "1", false);
 writer.RenderBeginTag(HtmlTextWriterTag.Table);
            writer.RenderBeginTag(HtmlTextWriterTag.Table);

 writer.RenderBeginTag(HtmlTextWriterTag.Tr);
            writer.RenderBeginTag(HtmlTextWriterTag.Tr);
 writer.RenderBeginTag(HtmlTextWriterTag.Td);
            writer.RenderBeginTag(HtmlTextWriterTag.Td);
 _nameLabel.RenderControl(writer);
            _nameLabel.RenderControl(writer);
 writer.RenderEndTag();  // Td
            writer.RenderEndTag();  // Td
 writer.RenderBeginTag(HtmlTextWriterTag.Td);
            writer.RenderBeginTag(HtmlTextWriterTag.Td);
 _nameTextBox.RenderControl(writer);
            _nameTextBox.RenderControl(writer);
 writer.RenderEndTag();  // Td
            writer.RenderEndTag();  // Td
 writer.RenderBeginTag(HtmlTextWriterTag.Td);
            writer.RenderBeginTag(HtmlTextWriterTag.Td);
 _nameValidator.RenderControl(writer);
            _nameValidator.RenderControl(writer);
 writer.RenderEndTag();  // Td
            writer.RenderEndTag();  // Td
 writer.RenderEndTag();  // Tr
            writer.RenderEndTag();  // Tr

 writer.RenderBeginTag(HtmlTextWriterTag.Tr);
            writer.RenderBeginTag(HtmlTextWriterTag.Tr);
 writer.RenderBeginTag(HtmlTextWriterTag.Td);
            writer.RenderBeginTag(HtmlTextWriterTag.Td);
 _passwordLabel.RenderControl(writer);
            _passwordLabel.RenderControl(writer);
 writer.RenderEndTag();  // Td
            writer.RenderEndTag();  // Td
 writer.RenderBeginTag(HtmlTextWriterTag.Td);
            writer.RenderBeginTag(HtmlTextWriterTag.Td);
 _passwordTextBox.RenderControl(writer);
            _passwordTextBox.RenderControl(writer);
 writer.RenderEndTag();  // Td
            writer.RenderEndTag();  // Td
 writer.RenderBeginTag(HtmlTextWriterTag.Td);
            writer.RenderBeginTag(HtmlTextWriterTag.Td);
 _passwordValidator.RenderControl(writer);
            _passwordValidator.RenderControl(writer);
 writer.RenderEndTag();  // Td
            writer.RenderEndTag();  // Td
 writer.RenderEndTag();  // Tr
            writer.RenderEndTag();  // Tr

 writer.RenderBeginTag(HtmlTextWriterTag.Tr);
            writer.RenderBeginTag(HtmlTextWriterTag.Tr);
 writer.AddAttribute(HtmlTextWriterAttribute.Colspan, "2");
            writer.AddAttribute(HtmlTextWriterAttribute.Colspan, "2");
 writer.AddAttribute(HtmlTextWriterAttribute.Align, "right");
            writer.AddAttribute(HtmlTextWriterAttribute.Align, "right");
 writer.RenderBeginTag(HtmlTextWriterTag.Td);
            writer.RenderBeginTag(HtmlTextWriterTag.Td);
 _button.RenderControl(writer);
            _button.RenderControl(writer);
 writer.RenderEndTag();  // Td
            writer.RenderEndTag();  // Td
 writer.RenderBeginTag(HtmlTextWriterTag.Td);
            writer.RenderBeginTag(HtmlTextWriterTag.Td);
 writer.Write(" ");
            writer.Write(" ");
 writer.RenderEndTag();  // Td
            writer.RenderEndTag();  // Td
 writer.RenderEndTag();  // Tr
            writer.RenderEndTag();  // Tr

 writer.RenderEndTag();  // Table
            writer.RenderEndTag();  // Table
 }
        }
 #endregion Overriden methods
        #endregion Overriden methods
 }
    }
4.控件状态以及性能方面的选择
上面的例子你会发现,再点击按钮以后,textbox值状态被保存了下来,还记得以前以Render方法直接呈现input标签的控件吗?在点击按钮以后textbox值状态是无法保存的.
第三篇的时候,我们讨论了数据回传的一些知识,我们也定义了一个textbox控件,在点击按钮以后,可以完美的保存其值状态.
至于原因,还请大家参考下文,作者已经分析的很清楚了.
ASP.NET 控件开发速成教程:生成复合控件
关于性能方面的问题,以下引用MSDN,具体大家还须参考MSDN
虽然创作复合控件相对比较容易,但是由于在撰写时必须创建子控件,所以会出现性能系统开销。如果您想优化控件的性能,可以通过重写 Render 方法,自己实现呈现逻辑。另外,必须实现控件所需的任何回发数据处理和回发事件处理。
本来想一起把事件处理和样式也写完了,但想写好篇幅太多了,这次就先写到这里吧,因为想把自己心里的意思表达明白还真的需要费一定时间去想的.下次我们继续讨论复合控件的事件和样式
本文示例代码下载
 
这次我们要讨论的是复合控件.本文无法一步到位完整介绍,因为讨论的篇幅比较大,所以分两次写,这次就先讲些基本概念吧,剩着的下次写.
好象复合控件网上已经有很多教程了,相信大家也看过很多.如果看过的朋友就当我再废话一便,没看过的朋友希望能给你带来帮助.
1.复合控件概念
复合控件跟用户控件有很多相似点,最大不同就是用户控件后缀为ascx,而复合控件编译后则为dll文件,还可以分发给大家使用,另外其他不同点还请参考MSDN吧,说白了,复合控件灵活性更大.
2.复合控件的呈现
(1)一般控件的呈现
从第一篇到第六篇为止,我们用以呈现控件的方法介绍过的有Render方法和RenderContents方法.回顾一下吧,看以下其中的一小段代码.
示例一
 public override void Render(HtmlTextWriter writer)
          public override void Render(HtmlTextWriter writer) {
      { 
  ..
.. writer.RenderBeginTag(HtmlTextWriterTag.Td);
              writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.AddAttribute(HtmlTextWriterAttribute.Name, "CreditCardNo");
          writer.AddAttribute(HtmlTextWriterAttribute.Name, "CreditCardNo"); writer.AddAttribute(HtmlTextWriterAttribute.Id, "CreditCardNo");
          writer.AddAttribute(HtmlTextWriterAttribute.Id, "CreditCardNo"); writer.AddAttribute(HtmlTextWriterAttribute.Type, "text");
          writer.AddAttribute(HtmlTextWriterAttribute.Type, "text"); writer.RenderBeginTag(HtmlTextWriterTag.Input);
          writer.RenderBeginTag(HtmlTextWriterTag.Input); writer.RenderEndTag();
          writer.RenderEndTag(); writer.RenderEndTag();
          writer.RenderEndTag(); 
          

 }
}以前我们所做的控件都是上面这样的写法.我们可以认为在Render方法实现了以下两个功能.
一.标签布局(如td标签,让控件呈现的好看点-_-)
二.呈现的标签(如input标签)
(2)复合控件的呈现方法
我们知道asp.net控件库里面已经提供给了我们像TextBox这样的控件了,就如组装电脑一下,你可以组装.net提供你现有的控件,然后重新拼凑成一个新的控件,这样便成了复合控件.但其呈现方法却又不同.
复合控件是以包含子控件的形式呈现的,具体的呈现交给子控件自己去做,因为子控件自身都已经实现了其呈现方法(每个控件都继承自Control类).假设你还不明白就看下面的图吧.
LabelTextBox1为复合控件,LabelTextBox2则不是.两者的呈现方式是不同的.具体实现方法请看下文

3.完成基本复合控件基本呈现
(1)首先你要熟悉以下的属性和方法
Control.CreateChildControls 方法用于创建子控件
Control.EnsureChildControls 方法用于确认是否已创建子控件,如果未创建完成的话则调用CreateChildControls 方法创建子控件
Control.ChildControlsCreated 属性 获取一个值,是否已创建子控件
(2)了解并实现INamingContainer接口
用户控件UserControl类则继承了INamingContainer接口,确包保子控件具有唯一的ID名称,那复合控件也需要实现这个接口达到一样的目的,这个是值得注意的地方.
复合控件以类撰写的方法来添加控件即CreateChildControls 方法,而非在Render方法中以下面方式实现
 writer.RenderBeginTag(HtmlTextWriterTag.Input);
writer.RenderBeginTag(HtmlTextWriterTag.Input);
在复合控件里Render方法的作用只是为我们提供布局的需要
下面看一个完成的代码,以微软的示例为例子.一个登录控件.
先看效果如下

再来看看代码吧,其实以下代码并不复杂.只不过属性多一点而已.看下面步骤
先定义控件类很简单.
然后定义几个公开的属性,注意每个属性都有一个EnsureChildControls 方法,因为返回的都是控件的属性,而我们又无法判断控件是否已经创建,所以须用此方法确保已创建控件,然后才可以使用其属性.
再通过类撰写方法CreateChildControls来添加子控件.
最后在Render方法实现布局以及用控件的RenderControl方法呈现自身标签内容,最后还要注意Render方法中的AddAttributesToRender方法,以前已经解释过这个方法的用处了,不调用此方法就无福享用WebControl类提供给你诸多样式属性了
以下注意的地方均以红字标出.说了一大堆了,看看下面代码,你明白了没?
示例二

 public class CompositeLogin : WebControl, INamingContainer
 public class CompositeLogin : WebControl, INamingContainer {
    {
 private Button _button;
        private Button _button; private TextBox _nameTextBox;
        private TextBox _nameTextBox; private Label _nameLabel;
        private Label _nameLabel; private TextBox _passwordTextBox;
        private TextBox _passwordTextBox; private Label _passwordLabel;
        private Label _passwordLabel; private RequiredFieldValidator _nameValidator;
        private RequiredFieldValidator _nameValidator; private RequiredFieldValidator _passwordValidator;
        private RequiredFieldValidator _passwordValidator;
 #region 属性
        #region 属性 [
        [ Bindable(true),
        Bindable(true), Category("Appearance"),
        Category("Appearance"), DefaultValue(""),
        DefaultValue(""), Description("按钮文本")
        Description("按钮文本") ]
        ] public string ButtonText
        public string ButtonText {
        { get
            get {
            { EnsureChildControls();
                EnsureChildControls(); return _button.Text;
                return _button.Text; }
            } set
            set {
            { EnsureChildControls();
                EnsureChildControls(); _button.Text = value;
                _button.Text = value; }
            } }
        }
 [
        [ Bindable(true),
        Bindable(true), Category("Default"),
        Category("Default"), DefaultValue(""),
        DefaultValue(""), Description("姓名")
        Description("姓名") ]
        ] public string Name
        public string Name {
        { get
            get {
            { EnsureChildControls();
                EnsureChildControls(); return _nameTextBox.Text;
                return _nameTextBox.Text; }
            } set
            set {
            { EnsureChildControls();
                EnsureChildControls(); _nameTextBox.Text = value;
                _nameTextBox.Text = value; }
            } }
        }
 [
        [ Bindable(true),
        Bindable(true), Category("Appearance"),
        Category("Appearance"), DefaultValue(""),
        DefaultValue(""), Description(
        Description( "必须输入姓名")
            "必须输入姓名") ]
        ] public string NameErrorMessage
        public string NameErrorMessage {
        { get
            get {
            { EnsureChildControls();
                EnsureChildControls(); return _nameValidator.ErrorMessage;
                return _nameValidator.ErrorMessage; }
            } set
            set {
            { EnsureChildControls();
                EnsureChildControls(); _nameValidator.ErrorMessage = value;
                _nameValidator.ErrorMessage = value; _nameValidator.ToolTip = value;
                _nameValidator.ToolTip = value; }
            } }
        }
 [
        [ Bindable(true),
        Bindable(true), Category("Apperance"),
        Category("Apperance"), DefaultValue(""),
        DefaultValue(""), Description("姓名标签")
        Description("姓名标签") ]
        ] public string NameLabel
        public string NameLabel {
        { get
            get {
            { EnsureChildControls();
                EnsureChildControls(); return _nameLabel.Text;
                return _nameLabel.Text; }
            } set
            set {
            { EnsureChildControls();
                EnsureChildControls(); _nameLabel.Text = value;
                _nameLabel.Text = value;
 }
            } }
        }
 [
        [ Browsable(false),
        Browsable(false), DesignerSerializationVisibility(
        DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden)
            DesignerSerializationVisibility.Hidden) ]
        ] public string Password
        public string Password {
        { get
            get {
            { EnsureChildControls();
                EnsureChildControls(); return _passwordTextBox.Text;
                return _passwordTextBox.Text; }
            } }
        }
 [
        [ Bindable(true),
        Bindable(true), Category("Appearance"),
        Category("Appearance"), DefaultValue(""),
        DefaultValue(""), Description(
        Description( "必须输入密码")
            "必须输入密码") ]
        ] public string PasswordErrorMessage
        public string PasswordErrorMessage {
        { get
            get {
            { EnsureChildControls();
                EnsureChildControls(); return _passwordValidator.ErrorMessage;
                return _passwordValidator.ErrorMessage; }
            } set
            set {
            { EnsureChildControls();
                EnsureChildControls(); _passwordValidator.ErrorMessage = value;
                _passwordValidator.ErrorMessage = value; _passwordValidator.ToolTip = value;
                _passwordValidator.ToolTip = value; }
            } }
        }
 [
        [ Bindable(true),
        Bindable(true), Category("Appearance"),
        Category("Appearance"), DefaultValue(""),
        DefaultValue(""), Description("密码标签")
        Description("密码标签") ]
        ] public string PasswordLabel
        public string PasswordLabel {
        { get
            get {
            { EnsureChildControls();
                EnsureChildControls(); return _passwordLabel.Text;
                return _passwordLabel.Text; }
            } set
            set {
            { EnsureChildControls();
                EnsureChildControls(); _passwordLabel.Text = value;
                _passwordLabel.Text = value;
 }
            } }
        } #endregion Properties delegated to child controls
        #endregion Properties delegated to child controls
 #region 方法
        #region 方法 //撰写
        //撰写 protected override void CreateChildControls()
        protected override void CreateChildControls() {
        { Controls.Clear();
            Controls.Clear();
 _nameLabel = new Label();
            _nameLabel = new Label();
 _nameTextBox = new TextBox();
            _nameTextBox = new TextBox(); _nameTextBox.ID = "nameTextBox";
            _nameTextBox.ID = "nameTextBox";
 _nameValidator = new RequiredFieldValidator();
            _nameValidator = new RequiredFieldValidator(); _nameValidator.ID = "validator1";
            _nameValidator.ID = "validator1"; _nameValidator.ControlToValidate = _nameTextBox.ID;
            _nameValidator.ControlToValidate = _nameTextBox.ID; _nameValidator.Text = "*";
            _nameValidator.Text = "*"; _nameValidator.Display = ValidatorDisplay.Static;
            _nameValidator.Display = ValidatorDisplay.Static;
 _passwordLabel = new Label();
            _passwordLabel = new Label();
 _passwordTextBox = new TextBox();
            _passwordTextBox = new TextBox(); _passwordTextBox.TextMode = TextBoxMode.Password;
            _passwordTextBox.TextMode = TextBoxMode.Password; _passwordTextBox.ID = "passwordTextBox";
            _passwordTextBox.ID = "passwordTextBox";
 _passwordValidator = new RequiredFieldValidator();
            _passwordValidator = new RequiredFieldValidator(); _passwordValidator.ID = "validator2";
            _passwordValidator.ID = "validator2"; _passwordValidator.ControlToValidate = _passwordTextBox.ID;
            _passwordValidator.ControlToValidate = _passwordTextBox.ID; _passwordValidator.Text = "*";
            _passwordValidator.Text = "*"; _passwordValidator.Display = ValidatorDisplay.Static;
            _passwordValidator.Display = ValidatorDisplay.Static;
 _button = new Button();
            _button = new Button(); _button.ID = "button1";
            _button.ID = "button1";
 this.Controls.Add(_nameLabel);
            this.Controls.Add(_nameLabel); this.Controls.Add(_nameTextBox);
            this.Controls.Add(_nameTextBox); this.Controls.Add(_nameValidator);
            this.Controls.Add(_nameValidator); this.Controls.Add(_passwordLabel);
            this.Controls.Add(_passwordLabel); this.Controls.Add(_passwordTextBox);
            this.Controls.Add(_passwordTextBox); this.Controls.Add(_passwordValidator);
            this.Controls.Add(_passwordValidator); this.Controls.Add(_button);
            this.Controls.Add(_button); }
        }
 //布局
        //布局 protected override void Render(HtmlTextWriter writer)
        protected override void Render(HtmlTextWriter writer) {
        { AddAttributesToRender(writer);
            AddAttributesToRender(writer);
 writer.AddAttribute(HtmlTextWriterAttribute.Cellpadding,
            writer.AddAttribute(HtmlTextWriterAttribute.Cellpadding, "1", false);
                "1", false); writer.RenderBeginTag(HtmlTextWriterTag.Table);
            writer.RenderBeginTag(HtmlTextWriterTag.Table);
 writer.RenderBeginTag(HtmlTextWriterTag.Tr);
            writer.RenderBeginTag(HtmlTextWriterTag.Tr); writer.RenderBeginTag(HtmlTextWriterTag.Td);
            writer.RenderBeginTag(HtmlTextWriterTag.Td); _nameLabel.RenderControl(writer);
            _nameLabel.RenderControl(writer); writer.RenderEndTag();  // Td
            writer.RenderEndTag();  // Td writer.RenderBeginTag(HtmlTextWriterTag.Td);
            writer.RenderBeginTag(HtmlTextWriterTag.Td); _nameTextBox.RenderControl(writer);
            _nameTextBox.RenderControl(writer); writer.RenderEndTag();  // Td
            writer.RenderEndTag();  // Td writer.RenderBeginTag(HtmlTextWriterTag.Td);
            writer.RenderBeginTag(HtmlTextWriterTag.Td); _nameValidator.RenderControl(writer);
            _nameValidator.RenderControl(writer); writer.RenderEndTag();  // Td
            writer.RenderEndTag();  // Td writer.RenderEndTag();  // Tr
            writer.RenderEndTag();  // Tr
 writer.RenderBeginTag(HtmlTextWriterTag.Tr);
            writer.RenderBeginTag(HtmlTextWriterTag.Tr); writer.RenderBeginTag(HtmlTextWriterTag.Td);
            writer.RenderBeginTag(HtmlTextWriterTag.Td); _passwordLabel.RenderControl(writer);
            _passwordLabel.RenderControl(writer); writer.RenderEndTag();  // Td
            writer.RenderEndTag();  // Td writer.RenderBeginTag(HtmlTextWriterTag.Td);
            writer.RenderBeginTag(HtmlTextWriterTag.Td); _passwordTextBox.RenderControl(writer);
            _passwordTextBox.RenderControl(writer); writer.RenderEndTag();  // Td
            writer.RenderEndTag();  // Td writer.RenderBeginTag(HtmlTextWriterTag.Td);
            writer.RenderBeginTag(HtmlTextWriterTag.Td); _passwordValidator.RenderControl(writer);
            _passwordValidator.RenderControl(writer); writer.RenderEndTag();  // Td
            writer.RenderEndTag();  // Td writer.RenderEndTag();  // Tr
            writer.RenderEndTag();  // Tr
 writer.RenderBeginTag(HtmlTextWriterTag.Tr);
            writer.RenderBeginTag(HtmlTextWriterTag.Tr); writer.AddAttribute(HtmlTextWriterAttribute.Colspan, "2");
            writer.AddAttribute(HtmlTextWriterAttribute.Colspan, "2"); writer.AddAttribute(HtmlTextWriterAttribute.Align, "right");
            writer.AddAttribute(HtmlTextWriterAttribute.Align, "right"); writer.RenderBeginTag(HtmlTextWriterTag.Td);
            writer.RenderBeginTag(HtmlTextWriterTag.Td); _button.RenderControl(writer);
            _button.RenderControl(writer); writer.RenderEndTag();  // Td
            writer.RenderEndTag();  // Td writer.RenderBeginTag(HtmlTextWriterTag.Td);
            writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.Write(" ");
            writer.Write(" "); writer.RenderEndTag();  // Td
            writer.RenderEndTag();  // Td writer.RenderEndTag();  // Tr
            writer.RenderEndTag();  // Tr
 writer.RenderEndTag();  // Table
            writer.RenderEndTag();  // Table }
        } #endregion Overriden methods
        #endregion Overriden methods }
    }4.控件状态以及性能方面的选择
上面的例子你会发现,再点击按钮以后,textbox值状态被保存了下来,还记得以前以Render方法直接呈现input标签的控件吗?在点击按钮以后textbox值状态是无法保存的.
第三篇的时候,我们讨论了数据回传的一些知识,我们也定义了一个textbox控件,在点击按钮以后,可以完美的保存其值状态.
至于原因,还请大家参考下文,作者已经分析的很清楚了.
ASP.NET 控件开发速成教程:生成复合控件
关于性能方面的问题,以下引用MSDN,具体大家还须参考MSDN
虽然创作复合控件相对比较容易,但是由于在撰写时必须创建子控件,所以会出现性能系统开销。如果您想优化控件的性能,可以通过重写 Render 方法,自己实现呈现逻辑。另外,必须实现控件所需的任何回发数据处理和回发事件处理。
本来想一起把事件处理和样式也写完了,但想写好篇幅太多了,这次就先写到这里吧,因为想把自己心里的意思表达明白还真的需要费一定时间去想的.下次我们继续讨论复合控件的事件和样式
本文示例代码下载
 
                    
                     
                    
                 
                    
                 

 
         
      
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号