上一篇文章中,我们简单的分析了页面的设计,今天我们来看页面中的动态部分。Master和Default页面中的主要控件如下表:
控件ID | 描述 |
Calendar | Asp.Net自带的日历控件,使用自带的样式,以后我们会使用该控件实现根据日期的查询。 |
ListView_BlogClass | ListView,用于显示日志分类。该控件生成的Html全部是连接,不需要响应事件,故EnableViewState设置为false。 |
ListView_BlogList | ListView,用于显示日志。该控件需要响应部分事件,所以其一部分子控件的EnableViewState设置为false,需要响应事件的部分设置为true。 |
LiteralPageCount | Literal,用于显示分页。这个控件结合我们自己的分页Helper使用。 |
在页面中,有很多需要格式化显示的地方,比如系统规定日期的显示规则为:如果时间中的时分秒都为零,则使用类似“2008年5月27日”的方式显示,否则,使用“2008年5月27日10:02:59”这样的方式显示;还有字符串的截断、布尔型类使用“是/否”显示、空字符串使用“ ”显示,以及各种枚举类型的显示等。对于这样的显示规则,我们使用Extension方法实现。如日期的显示使用以下代码(位于\DongBlog.UI\ToShowExtension.cs):
1: /// <summary>
2: /// 显示日期
3: /// </summary>
4: /// <param name="dateTime">要显示的日期</param>
5: /// <returns>日期字符串</returns>
6: public static String ToShow(this DateTime dateTime)
7: {
8: if (dateTime.TimeOfDay == TimeSpan.Zero)
9: return string.Format("{0:yyyy年MM月dd日}", dateTime);
10: else
11: return string.Format("{0:yyyy年MM月dd日} {0:T}", dateTime);
12:
13: }
在ListView_BlogList中,使用到了该方法,用于显示日志的更新时间:
<div runat="server" enableviewstate="false" class="BlogUpdateDateTime"> <%# ((DateTime)Eval("UpdateDateTime")).ToShow() %> </div>
该方法把UpdateDateTime求值后,转化为DateTime类型,然后调用ToShow()方法。如果你觉得类型转换不优雅的话,还可以这样写:
<div runat="server" enableviewstate="false" class="BlogUpdateDateTime"> <%# (Container.DataItem as Blog).UpdateDateTime.ToShow() %> </div>
这种写法对于显示实体的关系数据非常方便,比如显示该日志对应的分类,我们使用这样的写法:
分类:<a href="Default.aspx?BlogClassID=<%# (Container.DataItem as Blog).BlogClass.ID %>">
<%# (Container.DataItem as Blog).BlogClass.Name %></a>
这种方法利用了Linq对实体关系数据的Lazy Load,当读取Blog的BlogClass属性时,如果对应的BlogClass未被读取,则系统自动加载。
格式化显示的方法还能用于很多方面,例如,我们可以对PageBase类进行扩展,用于执行JavaScript:
1: /// <summary>
2: /// 采用JavaScript的Alert()方法向客户端显示信息
3: /// </summary>
4: /// <param name="page">页面</param>
5: /// <param name="message">要显示的信息</param>
6: public static void Js_ShowMessage(this Page page, string message)
7: {
8: if (page == null)
9: throw new ArgumentNullException("page");
10: page.Response.Write("<script language=javascript>
alert(\"" + message.Replace("\r\n", "\\n") + "\")</script>");
11: page.Response.Flush();
12: }
还可以对表示“钱”的数字的输入输出抽象出来,假设系统规定页面中的“钱”都以万为单位,而数据库中以分为单位储存、业务层以分为单位运算,则我们只需要以下扩展类:
1: /// <summary>
2: /// 金额的相关扩展
3: /// </summary>
4: public static class MoneyExtension
5: {
6: /// <summary>
7: /// 资金的单位
8: /// </summary>
9: public const long MONEY_UNIT = 10000 * 100;
10: /// <summary>
11: /// 资金的单位名称
12: /// </summary>
13: public const string MONEY_UNIT_NAME = "万元";
14:
15: /// <summary>
16: /// 将整数作为资金数额来显示,单位为:万。
17: /// </summary>
18: /// <param name="money">要显示的数额</param>
19: /// <param name="withUnit">是否包含单位</param>
20: /// <returns>要显示的字符串</returns>
21: public static String ToShowAsMoney(this long money, bool withUnit)
22: {
23: if (withUnit)
24: return (((float)money) / MONEY_UNIT).ToString() + MONEY_UNIT_NAME;
25: else
26: return (((float)money) / MONEY_UNIT).ToString();
27: }
28: /// <summary>
29: /// 将整数作为资金数额来显示,单位为:万。
30: /// </summary>
31: /// <param name="money">要显示的数额</param>
32: /// <param name="withUnit">是否包含单位</param>
33: /// <returns>要显示的字符串</returns>
34: public static String ToShowAsMoney(this long? money, bool withUnit)
35: {
36: if (money.HasValue)
37: return money.Value.ToShowAsMoney(withUnit);
38: else
39: return "无数据";
40: }
41:
42: /// <summary>
43: /// 将字符串转化为金额
44: /// </summary>
45: /// <param name="money">表示金额的字符串</param>
46: /// <returns>金额</returns>
47: public static long? ToMoney(this string money)
48: {
49: return string.IsNullOrEmpty(money) ? null :
new int?(Convert.ToInt32(Convert.ToDecimal(money) * MONEY_UNIT));
50: }
51: }
则我们在页面中可以使用:
<%#(Container.DataItem as PayPlanItem).Amount.ToShowAsMoney(true)%>
将“1230000分”格式化“1.23万”,如果ToShowAsMoney的参数为false,则会格式化为“1.23”。
而在代码中可以可以用:
project.Amount = TextBoxAmount.Text.ToMoney();
将用于基于“万元”填入的数额转化为分为单位的。这种方法的最大好处在于便于修改,假设系统以后要以“千”或者“百”或者“元”为单位,只要修改MONEY_UNIT和MONEY_UNIT_NAME两个常量即可。
页面辅助方法的使用还有很多,凡是页面实现逻辑,几乎都可以用该方法进行抽象。(Ruby On Rails的Helper方法也是这个思路)
回到我们的项目中来,现在,按下F5看一下效果了:
页面中ListView_BlogClass、ListView_BlogList和LiteralPageCount未绑定任何数据,所以没有显示出来。下一篇文章中,我们来看数据的绑定和显示。