今天想做些练习,做什么呢?还是练习一下动态变更样式吧。此博文在应用用户控件,接口,事件等知识,可以让你学习到编程的思想,如果是你来写,你是从哪一步开始,或是有另外种写法,都可达到相同的目标,绝招同途异路。
准备三种样式,在站点中创建一个目录"StyleSheet"用来存储样式文件,样式文件名分别为StyleSheet.css,SS_css1.css和SS_css2.css。
body{ }.textbox { border:solid 1px #000;}
body{ }.textbox { border:solid 1px #0094ff; }
body{ }.textbox { border:solid 1px #f00; }
创建一个aspx网页,创建时,把Place code in separate file选项选中,将代码放在单独的文件。
拉StyleSheet.css样式文件入aspx网页中,为样式链接添加ID和runat属性
<link id="StyleSheet1" runat="server" href="StyleSheet/StyleSheet.css" rel="stylesheet" />
还要往网页拉一个asp:TextBox控件,添加CssClass="textbox"属性。
<asp:TextBox ID="TextBox1" runat="server" CssClass="textbox"></asp:TextBox>
完整aspx如下:
现在需要做的是,网页运行时,能够变更它的样式:
protected void Page_Load(object sender, EventArgs e) { this.StyleSheet1.Attributes["href"] = "~/StyleSheet/" + "StyleSheet.css"; //变更样式名称 }
动画演示:
看完演示动画,教程也算完了,但Insus.NET却要疯了,不可能每变更一次,去打开代码来修改一次,这是最糟糕的做法。
怎样做呢?Insus.NET做到的在网页放置各种样式,用户点选就是了。根据例子,做好三张图片,放在站点的Img目录之下。
在.aspx网页显示此三张图片为图片铵钮:
<asp:ImageButton ID="ImageButton1" runat="server" ImageAlign="AbsMiddle" ImageUrl="~/Img/000.png" OnClick="ImageButton1_Click" /> <asp:ImageButton ID="ImageButton2" runat="server" ImageAlign="AbsMiddle" ImageUrl="~/Img/0094ff.png" OnClick="ImageButton2_Click" /> <asp:ImageButton ID="ImageButton3" runat="server" ImageAlign="AbsMiddle" ImageUrl="~/Img/f00.png" OnClick="ImageButton3_Click" /><br />
在.cs分别好各自的OnClick事件,关Comment out Page_Load事件内的代码:
protected void Page_Load(object sender, EventArgs e) { //this.StyleSheet1.Attributes["href"] = "~/StyleSheet/" + "StyleSheet.css"; //变更样式名称 } protected void ImageButton1_Click(object sender, ImageClickEventArgs e) { this.StyleSheet1.Attributes["href"] = "~/StyleSheet/" + "StyleSheet.css"; } protected void ImageButton2_Click(object sender, ImageClickEventArgs e) { this.StyleSheet1.Attributes["href"] = "~/StyleSheet/" + "SS_css1.css"; } protected void ImageButton3_Click(object sender, ImageClickEventArgs e) { this.StyleSheet1.Attributes["href"] = "~/StyleSheet/" + "SS_css2.css"; }
看看改变后的效果:
写到这里,Insus.NET又发现,每个事件中的代码冗余,因此Insus.NET把它抽取为一个方法,然后每个事件中直接执行这个方法,并传入相应的参数即可:
protected void ImageButton1_Click(object sender, ImageClickEventArgs e) { DynamicallySetStyleSheet("StyleSheet.css"); } protected void ImageButton2_Click(object sender, ImageClickEventArgs e) { DynamicallySetStyleSheet("SS_css1.css"); } protected void ImageButton3_Click(object sender, ImageClickEventArgs e) { DynamicallySetStyleSheet("SS_css2.css"); } //改善代码冗余,抽取为一个方法。 private void DynamicallySetStyleSheet(string cssName) { this.StyleSheet1.Attributes["href"] = "~/StyleSheet/" + cssName; }
呵呵,程序一步一步完善,可以想一下,日后样式需要增多,每增一次,又得来打开这个网页,添加图片按钮,添加事件...
是否可以不做到“改变一点而动全身”呢?程序是可以尝试一下的。
Insus.NET想到的是,把这部常变的代码,移至一个用户控件(ascx)内,有什么奕化,只更改此ascx即可。以下面在站点创建一个用户控件DynamicallySetupStyle.ascx:
然后把把三个按钮的html 剪下,粘帖于用户控件。
<%@ Control Language="C#" AutoEventWireup="true" CodeFile="DynamicallySetupStyle.ascx.cs" Inherits="DynamicallySetupStyle" %><asp:ImageButton ID="ImageButton1" runat="server" ImageAlign="AbsMiddle" ImageUrl="~/Img/000.png" OnClick="ImageButton1_Click" /><asp:ImageButton ID="ImageButton2" runat="server" ImageAlign="AbsMiddle" ImageUrl="~/Img/0094ff.png" OnClick="ImageButton2_Click" /><asp:ImageButton ID="ImageButton3" runat="server" ImageAlign="AbsMiddle" ImageUrl="~/Img/f00.png" OnClick="ImageButton3_Click" /><br />
三个OnClick事件也照搬:
using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;public partial class DynamicallySetupStyle : System.Web.UI.UserControl{ protected void Page_Load(object sender, EventArgs e) { } protected void ImageButton1_Click(object sender, ImageClickEventArgs e) { DynamicallySetStyleSheet("StyleSheet.css"); } protected void ImageButton2_Click(object sender, ImageClickEventArgs e) { DynamicallySetStyleSheet("SS_css1.css"); } protected void ImageButton3_Click(object sender, ImageClickEventArgs e) { DynamicallySetStyleSheet("SS_css2.css"); } }
此时的程序,在ascx的每个OnClick事件中,会找不到DynamicallySetStyleSheet(string xxx)方法,因为Insus.NET没有搬过去。怎样解决这个跨页访问方法的问题呢?不用担心,很简单的。
可以写一个接口,接口内的方法,就是与Page的private的方法一样:
using System;using System.Collections.Generic;using System.Linq;using System.Web;/// <summary>/// Summary description for ISetValable/// </summary>namespace Insus.NET{ public interface ISetValable { void DynamicallySetStyleSheet(string cssName); }}
然后在.aspx.cs件实作这个接口即可,实作之后,原先的Private已经变为Public修饰符了,参考下图高亮位置。
下面是用户控件的代码,参考高亮的位置:
最后是用户控件拉至.aspx网页中:
经过这样一改,有样式添加的话,我们只需要更改此用户控件即可。不必去动那个.aspx网页了。
写到此, 如果以添加多几个样式,供用户选择,需要添加一个ImageButton,还要写事件,这样的话,用户控件的事件也许会越来越多。Insus.NET又想到要重构这个用户控件。看看怎样才不用动很多地方。
在DynamicallySetupStyle.ascx网页,拿掉所有ImageButton代码,用PlaceHolder控件来替代。
<%@ Control Language="C#" AutoEventWireup="true" CodeFile="DynamicallySetupStyle.ascx.cs" Inherits="DynamicallySetupStyle" %><%--<asp:ImageButton ID="ImageButton1" runat="server" ImageAlign="AbsMiddle" ImageUrl="~/Img/000.png" OnClick="ImageButton1_Click" /> <asp:ImageButton ID="ImageButton2" runat="server" ImageAlign="AbsMiddle" ImageUrl="~/Img/0094ff.png" OnClick="ImageButton2_Click" /><asp:ImageButton ID="ImageButton3" runat="server" ImageAlign="AbsMiddle" ImageUrl="~/Img/f00.png" OnClick="ImageButton3_Click" />--%> <asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder><br />
在DynamicallySetupStyle.ascx.cs中,拿掉所有ImageButton事件:
//protected void ImageButton1_Click(object sender, ImageClickEventArgs e) //{ // DynamicallySetStyleSheet("StyleSheet.css"); //} //protected void ImageButton2_Click(object sender, ImageClickEventArgs e) //{ // DynamicallySetStyleSheet("SS_css1.css"); //} //protected void ImageButton3_Click(object sender, ImageClickEventArgs e) //{ // DynamicallySetStyleSheet("SS_css2.css"); //}
取而代之的是:
经过此一改,以后添加样式,或减少样式,只改上图高亮位置两行代码。