Clingingboy

<developer name=’'clingingboy">
<i:Interaction.Behaviors>
<clingingboy:madeControlBehavior />
</i:Interaction.Behaviors>
</developer>

博客园 首页 新随笔 联系 订阅 管理
  211 Posts :: 1 Stories :: 1439 Comments :: 484 Trackbacks
       上一篇写了控件样式的一些基础的东西,接着我们继续讨论asp.net控件开发的一些东西.

这次我们要讨论的是复合控件.本文无法一步到位完整介绍,因为讨论的篇幅比较大,所以分两次写,这次就先讲些基本概念吧,剩着的下次写.
好象复合控件网上已经有很多教程了,相信大家也看过很多.如果看过的朋友就当我再废话一便,没看过的朋友希望能给你带来帮助.

1.复合控件概念

复合控件跟用户控件有很多相似点,最大不同就是用户控件后缀为ascx,而复合控件编译后则为dll文件,还可以分发给大家使用,另外其他不同点还请参考MSDN吧,说白了,复合控件灵活性更大.

2.复合控件的呈现

(1)一般控件的呈现

从第一篇到第六篇为止,我们用以呈现控件的方法介绍过的有Render方法和RenderContents方法.回顾一下吧,看以下其中的一小段代码.

示例一
          public override void Render(HtmlTextWriter writer)
      
{
 ..
              writer.RenderBeginTag(HtmlTextWriterTag.Td);
          writer.AddAttribute(HtmlTextWriterAttribute.Name, "CreditCardNo");
          writer.AddAttribute(HtmlTextWriterAttribute.Id, "CreditCardNo");
          writer.AddAttribute(HtmlTextWriterAttribute.Type, "text");
          writer.RenderBeginTag(HtmlTextWriterTag.Input);
          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);

在复合控件里Render方法的作用只是为我们提供布局的需要

下面看一个完成的代码,以微软的示例为例子.一个登录控件.

先看效果如下




再来看看代码吧,其实以下代码并不复杂.只不过属性多一点而已.看下面步骤


定义控件类很简单.
然后定义几个公开的属性,注意每个属性都有一个EnsureChildControls 方法,因为返回的都是控件的属性,而我们又无法判断控件是否已经创建,所以须用此方法确保已创建控件,然后才可以使用其属性.
再通过类撰写方法CreateChildControls来添加子控件.
最后在Render方法实现布局以及用控件的RenderControl方法呈现自身标签内容,最后还要注意Render方法中的AddAttributesToRender方法,以前已经解释过这个方法的用处了,不调用此方法就无福享用WebControl类提供给你诸多样式属性了

以下注意的地方均以红字标出.说了一大堆了,看看下面代码,你明白了没?
示例二


4.控件状态以及性能方面的选择

上面的例子你会发现,再点击按钮以后,textbox值状态被保存了下来,还记得以前以Render方法直接呈现input标签的控件吗?在点击按钮以后textbox值状态是无法保存的.

第三篇的时候,我们讨论了数据回传的一些知识,我们也定义了一个textbox控件,在点击按钮以后,可以完美的保存其值状态.

至于原因,还请大家参考下文,作者已经分析的很清楚了.

ASP.NET 控件开发速成教程:生成复合控件

关于性能方面的问题,以下引用MSDN,具体大家还须参考MSDN

虽然创作复合控件相对比较容易,但是由于在撰写时必须创建子控件,所以会出现性能系统开销。如果您想优化控件的性能,可以通过重写 Render 方法,自己实现呈现逻辑。另外,必须实现控件所需的任何回发数据处理和回发事件处理。

本来想一起把事件处理和样式也写完了,但想写好篇幅太多了,这次就先写到这里吧,因为想把自己心里的意思表达明白还真的需要费一定时间去想的.下次我们继续讨论复合控件的事件和样式

本文示例代码下载
posted on 2006-09-04 22:36 Clingingboy 阅读(11392) 评论(28)  编辑 收藏 网摘 所属分类: B Asp.net组件开发

Feedback

Actually CreateChildControls can be used to control layout of child controls(for example, use table control.). In this way we can avoid Render method, especially useful for those developers who don't want to involve in HTML. Because all controls are created and rendered in server side, the performance is acceptable in general.
  回复  引用    

#2楼[楼主] 2006-09-06 08:52 Clingingboy      
@Chester

本人无法用英语答复你
我想你的意思是说,可以在CreateChildControls方法中使用Table控件来代替
Render()方法中table标签的呈现,这样有利于开发者,方便编程性.

但最后说到所有的控件都在服务器端创建和呈现,将有损性能,是不是这样的意思?

  回复  引用  查看    

#3楼 2006-09-21 14:41 飞飞[未注册用户]
我把控件拖到画面中提示:创建控件出错 或 呈现 控件出错
但是运行的时候却可以出来,不知道是为什么,我找了好久原因
希望赐教....

  回复  引用    

#4楼 2006-09-21 14:44 飞飞[未注册用户]
以上情况是在net2.0中出现的,在net1.1中却是一切正常....
  回复  引用    

#5楼[楼主] 2006-09-21 15:45 Clingingboy      
我也遇到过这种问题,有时候会因为缺少对象初始化,有时候重新启动下VS就可以了,可能代码写的不够周全.
  回复  引用  查看    

#6楼 2006-09-21 16:38 飞飞[未注册用户]
恩,我解决了,应该在定义控件的时候就给创建实例:
private Label _nameLabel = new Label();
private TextBox _nameTextBox = new TextBox();
而不是
private Label _nameLabel ;
private TextBox _nameTextBox ;
这样的话在CreateChildControls方法中就不用再实例化了

  回复  引用    

#7楼[楼主] 2006-09-21 17:17 Clingingboy      
@飞飞
恩,解决就好

  回复  引用  查看    

#8楼 2007-03-28 11:01 4444[未注册用户]
@Clingingboy
@Clingingboy
@Clingingboy
43433443

  回复  引用    

#9楼 2007-03-28 11:06 4444[未注册用户]
@司徒拔's Paradise
434343434

  回复  引用    

#10楼 2007-05-15 10:56 刘欢[未注册用户]
不好意思,自己试着做复合控件的时候有几个不明白的问题可以帮我解释下吗?
protected override void AddAttributesToRender(HtmlTextWriter writer)
{
writer.AddAttribute(HtmlTextWriterAttribute.Id, ClientID);
if (_renderPopupScript)
{
writer.AddAttribute("dp_htcURL", GetClientFileUrl("Calendar.htc"), false);
}
if (AutoPostBack)
{
writer.AddAttribute("dp_autoPostBack", "true", false);
}
.
.
.
}
其中添加名为"dp_htcURL","dp_autoPostBack"属性有什么意义,作用是什么?另外在writer.AddAttribute(HtmlTextWriterAttribute.Id, ClientID);
中是指:获取由asp.net生成的服务器控件标志符。这个又有什么作用?

  回复  引用    

#11楼[楼主] 2007-05-15 23:46 Clingingboy      
@刘欢
dp_htcURL和dp_autoPostBack可以不用去管他,两个是为了实现javascript功能而定义的非标准属性,
ClientID属性可以为控件获取回传对象,这里只是附了一个ID的值.效果不明白.示例的代码有些不规范.明白意思即可

  回复  引用  查看    

#12楼 2007-05-16 16:41 刘欢[未注册用户]

谢谢你啊~
再问你一个问题?

做好的控件拖到Web页面的时候经常会报这样一个错误:

呈现控件时出错-
发生了未处理的异常
未将对象引用设置到对象的实例

但是能够通过编译,这是怎么回事啊?有解决的办法吗?

  回复  引用    

#13楼 2007-05-17 10:16 刘欢[未注册用户]
谢谢你,这个问题我已经解决了!
  回复  引用    

#14楼[楼主] 2007-05-17 10:39 Clingingboy      
@刘欢
:)

  回复  引用  查看    

#15楼 2007-06-05 10:48 刘欢[未注册用户]
您好,我有个复合控件的问题一直解决不了,希望您帮帮忙。

我想做这样的一个复合控件,复合控件里有一个TextBox子控件,一个Button子控件,一个GridView子控件.将它拖到页面,点击Button的时候,数据库里指定的表会绑定到子控件GridView中,并显示出来,当我选择GridView中任意一行数据的时候,这行数据就会选中到TextBox中。

我的问题是,在写绑定代码的时候,不知道怎么获取复合控件中GridView子控件.以便将表绑定到GridView子控件中。
就像下面代码样,怎么样获取 “复合控件.GridView.Datasurce = .....;“
“复合控件.GridView.DataBind();

SqlConnection sonn = new SqlConnection("server=.;database=pubs;uid=sa;pwd=sa");
SqlCommand somm = new SqlCommand("select * from authors", sonn);
SqlDataAdapter sqldata = new SqlDataAdapter(somm);
DataSet ds = new DataSet();
sqldata.Fill(ds);
this.GridView1.DataSource = ds.Tables[0];
this.GridView1.DataBind();

  回复  引用    

#16楼[楼主] 2007-06-05 11:31 Clingingboy      
@刘欢
用事件冒泡呀,Repeater再套Repeater也是这样实现的

  回复  引用  查看    

请问:
怎样在复合控件的gridview子控件里添加一列 checkbox?

  回复  引用    

#18楼[楼主] 2007-06-12 08:34 Clingingboy      
@No西那``
声明checkBoxField,然后再添加,应该这样吧

  回复  引用  查看    


对,我也是这样做的,但是添加后,在gridview中显示不出checkbox,只是显示出一个空列.
在原GridView中可以通过设置"将此字段转换为TemplateField"而显示出来,但是在复合控件中的gridview子控件就不知道怎么实现了.

楼主帮个忙解决下了,这个问题都已经搞了一个多星期了..............

  回复  引用    

#20楼 2007-08-11 15:48 CsharpFish      
@No西那``
你把绑定CheckBox的一列该为模版列就OK了

  回复  引用  查看    

#21楼 2007-11-01 14:02 rweherr[未注册用户]
http://hur.cn/bbs/X_AdvCom_Vip.asp?UserID=76997这里的源代码不错啊,和这里的差不多
  回复  引用    




发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 494737




相关文章:

相关链接: