继续我们的话题吧.自定义控件.如果你还不熟悉自定义控件开发的话,还请看看我以前写了几篇,希望对你有帮助
1.1何处继承
自定义控件一般从以下几个基类(此处不包含数据控件)
一.Control类(所有服务器控件的基类,算是比较底层的类,如果控件功能比较简单,要求不多,可直接继承此类.)
二.WebControl类(标准控件的基类,继承此类,你可以继承其丰富的公共属性,若标准控件中的控件没有你需要的控件,你可以继承此类)
三.CompositeControl 类(2.0新增的类,此类继承自WebControl类,如果你需要制作复合控件,请从继承此类开始)
四.直接从内置控件继承(我们知道轮子只需要发明一遍,你的需求跟内置差不多的话,请考虑这么做)
1.2呈现控件
Control类Render方法为基本呈现方法,RenderContent方法是在Render方法之上的,其为控件加了一个标签,我认为RenderContent方法是为WebControl类中属性准备的.基本的方法继续深刻的去了解.
1.3与用户交互
纯粹的呈现控件还不够,我们需要传递数据,这就必然让我们了解自定义控件事件处理
1.4接触属性(见第五,九,十篇)
属性相对而言比较简单,也比较好理解,但其又比较麻烦,当控件属性太多,很容易乱,因此我们又认识了元数据。把属性进行了分类,如下图
为了更清晰了,把属性分好类别,我们又用另外做法,把多种同类型的属性,定义在一个大的属性里面,称之为复杂属性,如下图
属性已经够多了,不紧如此,我们还知道属性的每种类型可能不一样,而在呈现之后都是呈现字符串形式,简单属性.net已为你处理好转换,当你自定义复杂属性以后,你则需要自己为你定义的复杂属性定义一个类型转换器(见第九篇)。属性还有另外一种做法,就是可以把属性当成集合属性来用.可以说是特殊话的复杂控件,这样做可以提供给一些列表控件使用(见第10篇) 属性用途还真不少
1.5控件样式
控件怎么能缺样式,我们自然需要它,在此我们再次认识到了WebControl类.当然也了解到了Style类及其子类,只要你了解了其中的几个方法你就可以自定义控件样式了
1.6复合控件
复合控件的功能往往比较强大,它利用当前已经存在的控件进行组装成一个新的控件,在此过程中我们学习了在复合控件中定义事件以及定义样式.
1.7视图状态
不得不谈的一个话题,一般我们为控件定义的属性都以视图状态的形式保存,然而复杂属性的定义和控件样式定义则需要你了解如何自定义视图状态。
最后我们还讨论了如何为控件添加客户端功能,还有为控件定义生成器。好了,总结终于告一段落,以上写了两遍,第一遍写的时候保存后数据居然丢失了,痛苦啊。
下面我们分享一些小技巧,或许大家早已经知道了,为了以后更好的学习,我把命名控件全部更改为AspDemo.CustomComponents。此次下载的源码包括1-16篇的全部的示例代码,如果有什么错误还请大家指出。
补充
一.嵌入资源的使用
1.嵌入控件图标
内置控件都有自己的图标,很多人也很喜欢为自己的控件做个图标,那如何做呢?
我们只需要使用ToolboxBitmap元数据就可以了,你需要了解其构造函数,用法如下
namespace AspDemo.CustomComponents
{
[ToolboxBitmap(typeof(ImageControl), "Resources.Image.bmp")]
public class ImageControl : WebControl
{
}
}
注意点:
(1)图标的位置位于,以你默认命名空间为根目录,以点语法的方式来指定图标位置,(即图标路径为/Resources),否则的话以你控件类型命名控件为根目录,(即图标路径为CustomComponents/Resources),大家可以尝试一下
(2)在属性面板指明图标文件为嵌入的资源,如下图
2.嵌入其他资源文件
记得以前我们做了一个控件需要一个js文件,当需要使用这个控件的话,则也需要使用js文件,这样给别人用的话很不方面,我们可以把js文件作为嵌入资源使用来解决这一问题.以下例子来自MSDN,这里只是让大家知道如何使用
[assembly: WebResource("AspDemo.CustomComponents.Resources.AspDemo.CustomComponents.ResourceLabel.image1.jpg", "image/jpeg")]
[assembly: WebResource("AspDemo.CustomComponents.Resources.AspDemo.CustomComponents.ResourceLabel.help.htm", "text/html", PerformSubstitution = true)]
namespace AspDemo.CustomComponents
{
public class ResourceLabel : Control
{
protected override void CreateChildControls()
{
// Create a new Image control.
Image _img = new Image();
//获取资源文件引用
_img.ImageUrl = this.Page.ClientScript.GetWebResourceUrl(this.GetType(), "AspDemo.CustomComponents.Resources.AspDemo.CustomComponents.ResourceLabel.image1.jpg");
this.Controls.Add(_img);
// Create a new Label control.
Label _lab = new Label();
_lab.Text = "A composite control using the WebResourceAttribute class.";
this.Controls.Add(_lab);
// Create a new HtmlAnchor control linking to help.htm.
HtmlAnchor a = new HtmlAnchor();
a.HRef = this.Page.ClientScript.GetWebResourceUrl(typeof(ResourceLabel), "AspDemo.CustomComponents.Resources.AspDemo.CustomComponents.ResourceLabel.help.htm");
a.InnerText = "help link";
this.Controls.Add(new LiteralControl("</br>"));
this.Controls.Add(a);
}
}
}
注意点:
(1)跟上面第二点一样
(2)路径为以默认命名空间为根路径,然后以点语法获取文件路径(AspDemo.CustomComponents为命名空间,Resources为文件夹,AspDemo.CustomComponents.ResourceLabel.help.htm此为文件名称)
OK,这样就算完成了
二.持久性控件状态
下面也只给出部分代码(来自MSDN),这方面资料我相信已经很多了,只当补充
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
Page.RegisterRequiresControlState(this);
}
protected override object SaveControlState()
{
object obj = base.SaveControlState();
if (indexValue != 0)
{
if (obj != null)
{
return new Pair(obj, indexValue);
}
else
{
return (indexValue);
}
}
else
{
return obj;
}
}
protected override void LoadControlState(object state)
{
if (state != null)
{
Pair p = state as Pair;
if (p != null)
{
base.LoadControlState(p.First);
indexValue = (int)p.Second;
}
else
{
if (state is int)
{
indexValue = (int)state;
}
else
{
base.LoadControlState(state);
}
}
}
}
三.客户端回调
ASP.NET 2.0 Unleashed单独列出了一章来讲JavaScript在自定义控件中的使用,我想大家还是看书上例子吧,个人感觉很好,非常容易理解.而且学会这个的话,还可以看的懂AtlasControlToolkit里面的几个控件,几乎都用到了这种技术.
四.配置文件
(1)在web.config中预先定义控件标签和注册控件,从而可以在每个页面省去
使用 @ Register 指令
<pages>
<controls>
<add tagPrefix="aspDemo" namespace="AspDemo.CustomComponents" assembly="AspDemo.CustomComponents"/>
</controls>
</pages>
(2)控件映射
url可以映射,控件也可以,我们在配置Ajax环境的时候就用到了此方法
<pages>
<tagMapping>
<add tagType="System.Web.UI.WebControls.RequiredFieldValidator" mappedTagType="System.Web.UI.Compatibility.RequiredFieldValidator, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</pages>
五.在工具栏上隐藏控件
再讲一个小东西,当定义的控件,不需要在工具栏上显示的话,可以用此元数据把控件隐藏起来
[ToolboxItem(false)]
public class ImageControl : WebControl
{
}