从简单做起---ASP.NET复合控件(修定版)

从简单做起---ASP.NET复合控件

 

在你的网页应用程序里面添加用户控件,真的很简单。事实上,你只是做了网页的一部分,添加HTML,然后在应用程序里面使用。尽管用着很简单,但是不方便在应用程序间共享。有一种控件复合性控件,做起来很复杂,但是用着很方便,它可以很方便地在不同的应用程序之间多次使用。这里我们就简单介绍这种控件的生成方法。

 

我们可以使用MS内置控件,如Textbox等来组建你的复合控件,当然,也可以用自己定义Layout。在这里我们放三个Textbox,让用户来输入日期,当然还有一些逻辑代码来合并这些日期成为一个完整的日期格式。

 

在这个DEMO中你要建两个工程,一个是复合控件工程Web Control Library,一个是引用这个复合控件的WEB程序。在这里,我们的前者工程叫做,DateEditBox,完成后,会有一个DateEditBox的类。以下这个类的主要信息:

 

 

namespace MyControls
{
   [DefaultProperty(
"Value")]
   [ToolboxData(
"<{0}:DateEditBox runat=server></{0}:DateEditBox>")]
   
public class DateEditBox : CompositeControl
   
{
      
private TextBox txtMonth = new TextBox();
      
private TextBox txtDay   = new TextBox();
      
private TextBox txtYear  = new TextBox();

      
protected override void OnInit(EventArgs e)
      
{
         
base.OnInit(e);
         txtMonth.ID        
= this.ID + "_month";
         txtMonth.MaxLength 
= 2;
         txtMonth.Width     
= this.Width;

         txtDay.ID        
= this.ID + "_day";
         txtDay.MaxLength 
= 2;
         txtDay.Width     
= this.Width;

         txtYear.ID        
= this.ID + "_year";
         txtYear.MaxLength 
= 4;
         txtYear.Width     
= this.Width;
      }


      [Bindable(
true)]
      [Category(
"Appearance")]
      [DefaultValue(
"")]
      [Localizable(
true)]
      
public DateTime Value
      
{
         
get
         
{
            EnsureChildControls();
            
if (txtMonth.Text == "" || txtDay.Text == "" ||
                txtYear.Text 
== "")
               
return DateTime.MinValue;
            
else
               
return new DateTime(Convert.ToInt32(txtYear.Text),
                  Convert.ToInt32(txtMonth.Text),
                  Convert.ToInt32(txtDay.Text));
         }


         
set
         
{
            EnsureChildControls();
            txtMonth.Text 
= value.Month.ToString();
            txtDay.Text   
= value.Day.ToString();
            txtYear.Text  
= value.Year.ToString();
         }

      }

      
protected override void CreateChildControls()
      
{
         
this.Controls.Add(txtMonth);
         
this.Controls.Add(txtDay);
         
this.Controls.Add(txtYear);
         
base.CreateChildControls();
      }

      
public override void RenderControl(HtmlTextWriter writer)
      
{
         writer.RenderBeginTag(HtmlTextWriterTag.Table);
         writer.RenderBeginTag(HtmlTextWriterTag.Tr);
         writer.RenderBeginTag(HtmlTextWriterTag.Td);
         txtMonth.RenderControl(writer);
         writer.RenderEndTag();    
// td
         writer.RenderBeginTag(HtmlTextWriterTag.Td);
         writer.Write(
"/");
         writer.RenderEndTag();    
// td
         writer.RenderBeginTag(HtmlTextWriterTag.Td);
         txtDay.RenderControl(writer);
         writer.RenderEndTag();    
// td
         writer.RenderBeginTag(HtmlTextWriterTag.Td);
         writer.Write(
"/");
         writer.RenderEndTag();    
// td
         writer.RenderBeginTag(HtmlTextWriterTag.Td);
         txtYear.RenderControl(writer);
         writer.RenderEndTag();    
// td
         writer.RenderEndTag();    // tr
         writer.RenderEndTag();    // table
      }

   }

}


 

 

这个类有点复杂,让我们来分析一下。我个内是以一些属性定义开始的。第一个是默认值,用来指定值的属性。第二个是用来指定本控件可以用在WEB页面的,一般是从VS工具箱拖拉到页面上的。你也注意到了,这个类是继承至CompositeControl,,这个内是专为自定义复合控件定制的。关于这个类的详细信息可以查看MSDN

 

OnInit事件里,我们给这三个子控件设置一些默认值,如ID,宽度,字长等。我们设置ID以复控件ID开头,是因为在后面我们将用这些ID来查找这些控件。

 

我们有值属性设置器,就可以很方便的设置和读取它们各自的值,当然,在这里,你完全可以加入一些基本的验证。在这里就不说这些了。接下来就是CreateChildControls方法和RenderControl方法。前者可以让页面在回传的时候保存控件状态。如果没有这方法,你的子控件就不能保存视图状态,所以也不能正常显示在回传页面的时候。后一个方法负责让你的控件在页面上正常显示。这样的话,你的控件就会显示以下格式:

table
   tr
      td [txtMonth] /td
      td [/] /td
      td [txtDay] /td
      td [/] /td
      td [txtYear] /td
   /tr
/table

 

当然在HtmlTextWriter里面你也可以自己定义你的样式,排版等。如果你想在其它工程中引用这个控件的话,首先要编译,成功后会在BIN里面出现*.dll,引用这个DLL在新的工程里面,然后,在你的页面代码里加入如下代码:

 

<%@ Register Assambly=”myControls” Namespace=”myControls” TagPrefix=”MC” %>

 

一旦在工程里添加DLL引用后,工程会自动COPY这个DLL到BIN目录里面,在你的VS智能感知里面会出现类如MC:DateEditBox,在后台代码里面,你可以看到控件的属性值。

 

总结:

你还可以添加更多的功能在这个控件里,但是这里只是显示最基本的控件需要代码。创建新的子控件,设置它们的ID值,添加到控件集合里,最后呈现出来。至此一个复合控件就完成了。之后,在添加更多的事件,属性和方法等,让你的控件看起来更酷一些。

P.S.大家可以注意到在这段代码里面有个EnsureChildControls()方法,在作者的原文中没有相关的说明,非常感谢wangzhe.king在这里提出问题,我想大多数朋友都不太清楚,这个方法,在此说明一下:

这个方法在检测当前ChildControlsCreated的值,如果是FALSE的话,那么就调用这个方法。ASP.NET调用这个方法,以保证子控件已经构建完毕。在大多数情况下,自定义服务器控件开发者不必重写这个方法。这个方法大多数用在属性器里面,因为在设置或得到属性值以前,你要检测子控件是否已经构建了。

官方详细解说,点此查看!
译自:CodeGuru 原文地址

posted @ 2006-10-23 10:06  Henry Liu  阅读(1791)  评论(5编辑  收藏  举报