虽然现在网上可以找到n多第三方控件,可我总是看那些单独的dll不爽,在微软提供的标准控件无法满足实际需求时,大多采取扩展标准控件定制个性功能的方法解决,本文描述了给ImageButton控件增加鼠标悬浮变换图像功能的实现步骤。——cncxz(虫虫) 2006-3-22 安装上vs.net2005之后,就发现asp.net2.0中的主题和外观功能用起来比较方便,例如ImageButton控件,只要在不同主题下的外观文件(*.Skin)中设置好相应的imageurl属性,在更换主题时做好SkinID关联的ImageButton控件就会指向不同的图片了。后来看到QuickStart中“运行”、“查看源代码”两个按钮效果后,就想,加上一个鼠标悬浮变换图像的功能是不是更好一点?
首先查看了一下QuickStart中的实现代码,发现它是直接在Html中作的构造:
<a target="<%=_target%>" href="<%=RunSample%>"> <img alt="Run Sample" border="0" src="<%=HttpRuntime.AppDomainAppVirtualPath%>/images/button_run.gif" onmouseout="this.src='<%=HttpRuntime.AppDomainAppVirtualPath%>/images/button_run.gif'" onmouseover="this.src='<%=HttpRuntime.AppDomainAppVirtualPath%>/images/button_run-over.gif'" onmousedown="this.src='<%=HttpRuntime.AppDomainAppVirtualPath%>/images/button_run-down.gif'" onmouseup="this.src='<%=HttpRuntime.AppDomainAppVirtualPath%>/images/button_run.gif'" /></a> 于是使用Reflector反编译System.Web.dll,找到ImageButton的源码,原来ImageButton就是一个实现了IPostBackDataHandler、IPostBackEventHandler、IButtonControl三个接口的Image,打开Image的源码,看到了如下的ImageUrl属性定义代码:
[WebCategory("Appearance"), Editor("System.Web.UI.Design.ImageUrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor)), DefaultValue(""), UrlProperty, Bindable(true), WebSysDescription("Image_ImageUrl")] public virtual string ImageUrl { get { string text1 = (string) this.ViewState["ImageUrl"]; if (text1 != null) { return text1; } return string.Empty; } set { this.ViewState["ImageUrl"] = value; } } 照葫芦画瓢,很简单地就给出了扩展属性ImageOverUrl的代码,此属性用以提供鼠标悬浮时显示的图片。
public virtual string ImageOverUrl { get { string text1 = (string)this.ViewState["ImageOverUrl"]; if (text1 != null) { return text1; } return string.Empty; } set { this.ViewState["ImageOverUrl"] = value; } } 下一步就是给Image添加onmouseover和onmouseout客户端事件了。由于ImageButton是按钮,所以在鼠标点击时必然要触发按钮事件,而同时它又是图片,所以应该是在图片的onclick触发按钮事件,因而我们应该可以参照其对onclick的处理方式撰写我们的onmouseover和onmouseout代码。再回到ImageButton的源码中来,发现它是通过重写AddAttributesToRender方法完成onclick功能设计的,代码如下:
protected override void AddAttributesToRender(HtmlTextWriter writer) { Page page1 = this.Page; if (page1 != null) { page1.VerifyRenderingInServerForm(this); } writer.AddAttribute(HtmlTextWriterAttribute.Type, "image"); string text1 = this.UniqueID; PostBackOptions options1 = this.GetPostBackOptions(); if ((text1 != null) && ((options1 == null) || (options1.TargetControl == this))) { writer.AddAttribute(HtmlTextWriterAttribute.Name, text1); } bool flag1 = base.IsEnabled; string text2 = string.Empty; if (flag1) { text2 = Util.EnsureEndWithSemiColon(this.OnClientClick); if (base.HasAttributes) { string text3 = base.Attributes["onclick"]; if (text3 != null) { text2 = text2 + Util.EnsureEndWithSemiColon(text3); base.Attributes.Remove("onclick"); } } } if (this.Enabled && !flag1) { writer.AddAttribute(HtmlTextWriterAttribute.Disabled, "disabled"); } base.AddAttributesToRender(writer); if ((page1 != null) && (options1 != null)) { page1.ClientScript.RegisterForEventValidation(options1); if (flag1) { string text4 = page1.ClientScript.GetPostBackEventReference(options1, false); if (!string.IsNullOrEmpty(text4)) { text2 = Util.MergeScript(text2, text4); } } } if (text2.Length > 0) { writer.AddAttribute(HtmlTextWriterAttribute.Onclick, text2); if (base.EnableLegacyRendering) { writer.AddAttribute("language", "javascript", false); } } } 于是,onmouseover和onmouseout的设计代码也就出来了:
protected override void AddAttributesToRender(HtmlTextWriter writer) { bool flag1 = base.IsEnabled; if (!string.IsNullOrEmpty(this.ImageOverUrl) && flag1) { string Textover = "this.src='" + base.ResolveClientUrl(this.ImageOverUrl) + "';"; string Textout = "this.src='" + base.ResolveClientUrl(this.ImageUrl) + "';"; if (base.HasAttributes) { string temp; temp = base.Attributes["onmouseover"]; if (temp != null) { Textover = Textover + temp; base.Attributes.Remove("onmouseover"); } temp = base.Attributes["onmouseout"]; if (temp != null) { Textout = Textout + temp; base.Attributes.Remove("onmouseout"); } } base.Attributes.Add("onmouseover", Textover); base.Attributes.Add("onmouseout", Textout); } base.AddAttributesToRender(writer); }