在日常项目开发中,我们会经常用到自定义控件,我们通过一个简单的例子来说明,在日常项目中我们经常会用到图片,或者图片控件,我们以ImageButton为例来说明。
<asp:ImageButton ID="imgbtn" runat="server" ImageUrl="~/Images/Add.png" />
很多时候我们需要在很多页面上放上面这段代码,每次都要重复设置ImageUrl 当图片路径换了。或者图片名称换了,我们需要替换很多地方。有没有更简单的方法呢,使用自定义控件。在项目中我们经常使用一些添加 删除,修改的按钮图片 来代替按钮。我们以此为例来说明。
1、创建一个类库项目,或者web控件库项目都可以,添加一个类(Class)。继承ImageButton
public class CustImageButton : ImageButton { }
2、我们在同一个项目中,一般使用的图片大多是一样的。比如添加 删除,这些按钮图片。那么我们在定义一个枚举 用于区分不同的图片,我们定义了四种类型 添加 修改 查看 删除
public enum CustImageType { Add, Edit, View, Delete }
3、定义一个属性,用于设定 图片的类型
[Bindable(true)] [Category("Appearance")] [DefaultValue(CustImageType.Add)] [Localizable(true)] public CustImageType ImageType { get { return ViewState["ImageType"] == null ? CustImageType.Add : (CustImageType)ViewState["ImageType"]; } set { ViewState["ImageType"] = value; } }
我们定义了一个自定义的属性ImageType,类型是CustImageType枚举类型。为了便于在控件的属性窗口显示,我们设置了几个特性
[Bindable(true)] 指定成员是否通常用于绑定 [Category("Appearance")] 指定当属性或事件显示在一个设置为“按分类顺序”模式的 System.Windows.Forms.PropertyGrid 控件中时,用于给属性或事件分组的类别的名称 [DefaultValue(CustImageType.Add)] 指定属性的默认值 [Localizable(true)] 指定属性是否应本地化
4、重写ImageButton控件的Render方法
protected override void Render(HtmlTextWriter writer) { switch (ImageType) { case CustImageType.Add: this.ImageUrl = this.ResolveUrl("~/Images/Add.png"); break; case CustImageType.Edit: this.ImageUrl = this.ResolveUrl("~/Images/Edit.png"); break; case CustImageType.Delete: this.ImageUrl = this.ResolveUrl("~/Images/delete.png"); break; case CustImageType.View: this.ImageUrl = this.ResolveUrl("~/Images/View.png"); break; } base.Render(writer); }
在页面中引用如下:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="WebDemo1.Index" %> <%@ Register Assembly="CustControl" Namespace="CustControl" TagPrefix="cc1" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> </head> <body> <form id="form1" runat="server"> <div> <cc1:CustImageButton ID="CustImageButton1" ImageType="View" runat="server" /> </div> </form> </body> </html>
运行效果
换成如下代码
<cc1:CustImageButton ID="CustImageButton1" ImageType="Edit" runat="server" />
显示
可以看出 非常方便,只需要在属性窗口设置 ImageType 就可以轻松实现图片显示。
但是这样也有一个问题,我们使用的ImageUrl的路径是我们web项目中的路径,当我们的路径改了,或者图片换了,我们仍然需要重复的去修改程序,而且每次引用这个控件 我们都需要在web项目中添加对应路径的图片,非常麻烦,有木有更好的方法呢,当然 那就是使用嵌入的资源这是.NET2.0开始引入的。
我们在我们的控件项目中添加刚才用到的4张图片。
选中其中一张图片右键点击属性 把生成操作类型改成嵌入的资源
然后在我们的应用程序集文件中添加
添加如下代码
[assembly: WebResource("CustControl.Images.Add.png", "img/png")] [assembly: WebResource("CustControl.Images.delete.png", "img/png")] [assembly: WebResource("CustControl.Images.Edit.png", "img/png")] [assembly: WebResource("CustControl.Images.View.png", "img/png")]
CustControl是命名空间,Images是文件夹名称后面是图片,用.分隔
接下来就是我们如何在程序中访问这些图片了。
.net提供了访问web资源文件的类和方法,我们这地方使用
Page.ClientScript.GetWebResourceUrl
方法来访问
所以我们修改Render方法中的代码为:
protected override void Render(HtmlTextWriter writer) { switch (ImageType) { case CustImageType.Add: //Page.ClientScript.GetWebResourceUrl()获取对程序集内资源的 URL 引用 this.ImageUrl = this.Page.ClientScript.GetWebResourceUrl(this.GetType(), "CustControl.Images.Add.png"); break; case CustImageType.Edit: this.ImageUrl = this.Page.ClientScript.GetWebResourceUrl(this.GetType(),"CustControl.Images.Edit.png"); break; case CustImageType.Delete: this.ImageUrl = this.Page.ClientScript.GetWebResourceUrl(this.GetType(),"CustControl.Images.delete.png"); break; case CustImageType.View: this.ImageUrl = this.Page.ClientScript.GetWebResourceUrl(this.GetType(),"CustControl.Images.View.png"); break; } base.Render(writer); }
在页面不需要引入图片 使用效果也是一样。很方便吧,试试吧!
直接上代码: