NBearV3教程——Web篇


本教程结合实例演示NBear.Web提供的Page/MasterPage/UserControl扩展基类。您将看到,使用这些基类能大大提高ASP.NET 2.0网页开发速度,轻松获得Ajax和多语言支持等功能。对应的源码包含在从sf.net下载的zip包中的tutorials\Web_Tutorial目录中。

    重要说明

    本文讨论的内容只涉及NBear.Web这一个程序集,如果要在您自己的Web项目中使用本文所讨论的功能,只需要添加到NBear.Web.dll的引用。NBear是一个基于.Net Framework 2.0/C# 2.0/ASP.NET 2.0的框架,因此,本文讨论的内容只能用于ASP.NET 2.0开发。

    本文只讨论了NBear.Web中由NBear.Web.UI命名空间下的Page/MasterPage/UserControl这组扩展基类中定义的功能,因此,要在网页中使用这些组件的功能,必须将这些类设为您的WebForm页面,MasterPage页面或User Control的基类。

    由于为Page,MasterPage和UserControl这三个基类所作的扩展基本上是等价的,所以,本文下面的内容,主要演示对于Page这个基类的扩展功能,对于MasterPage和UserControl使用方法类似,只需保证使MasterPage和UserControl继承相应的基类即可。

    Helper Methods

    示例代码中的HelperMethodsDemo.aspx页面演示了一组NBear.Web.UI.Page基类的扩展辅助方法。

    1) GetIntParam()/GetStringParam()/GetDateTimeParam()。这组方法用于方便地获取从QueryString和Form传递而来的参数。如果网页包含相同键值的Form参数和QueryString参数,则优先返回Form参数。

    下面的代码简单的使用这组函数,并输出参数的值:

Response.Write(string.Format("intParam = {0}<br />", GetIntParam("intParam", 0)));
Response.Write(string.Format("strParam = {0}<br />", GetStringParam("strParam", string.Empty)));
Response.Write(string.Format("dtParam = {0}<br />", GetDateTimeParam("dtParam", DateTime.MinValue)));

    注意,这组函数包含两个参数,第二个参数指定默认的错误返回值,如果指定的键值不存在,或类型转换失败,则返回该错误返回值。

    2) StrongTyped<IEntityType>()。该方法用于将一个任意类型的对象转换为指定的强类型对象,从而简化形如(ReturnType)obj这样的语法。该方法尤其适合于用于页面的数据绑定表达式中,代替基于反射的eval语法。

    下面的示例将一个弱类型的Session值转换为一个强类型的对象:

Session["hello time"] = DateTime.Now;
Response.Write(string.Format("Test StrongTyped&lt;T&gt;(), current time ticks = {0}<br />", StrongTyped<DateTime>(Session["hello time"]).Ticks));

    3) TextToHtml()/ToXXXString()。这组方法帮助进行常见的字符串转换。执行示例页面可以看到其中两个方法的演示,这里就不列举了。

    ClientScriptFactory

    可以通过 Page.ClientScriptFactory访问一组用于生成客户端JS脚本的服务端方法,包含了常见的一些JS代码的构造封装。在服务端构造客户端JS的好处可以使得构造客户端脚本的过程获得编译期的错误检测,避免手写JS代码的一些不小心的不那么容易调试的错误。

    示例代码中的ClientScriptFactoryDemo.aspx页面演示了使用ClientScriptFactory的两种典型场景。

    一种是在aspx页面中直接输出脚本。例如:

<%= ClientScriptFactory.WrapScriptTag(ClientScriptFactory.PopAlert("Page Loaded")) %>

    该语句将直接向页面输出一个<script>块,包含一个alert效果。注意,如果不使用WrapScriptTag的话,自然生成的脚本就不会包含在一个script中,当在某一段script块中插入部分JS片段时,不需包含WrapScriptTag。

    第二种也是非常常见的使用方法,则是在页面的某个Postback方法执行完毕后,直接在事件处理函数中Response一段脚本,给出一个客户端提示。例如,下面的代码在一个事件处理函数中输出了一段相对复杂的客户端JS脚本:

Response.Write(ClientScriptFactory.WrapScriptTag(string.Format("var result = {0}; if (result) {1} else {2}", ClientScriptFactory.PopConfirm("Are you sure?"), ClientScriptFactory.PopAlert("Yes"), ClientScriptFactory.PopAlert("No")), ClientScriptFactory.PopAlert("Done")));
 LoadResources()/GetString()

    这组方法提供了基于.resx和.resources资源文件,支持多语言网站构架的功能。Global.asax和GlobalizationDemo.aspx页面演示了这组方法的使用。

    注:ASP.NET 2.0本身就提供了很不错的多语言支持方案,本组件中提供的可以作为另一个选择,但是一般还是推荐使用ASP.NET 2.0默认提供的方案。

    在Global.asax中的Application_Start事件中,初始化资源为一个默认语言: void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
if (NBear.Web.UI.WebHelper.DefaultCulture.ToString().ToLower() != "en-us")
{
NBear.Web.UI.WebHelper.DefaultCulture = new System.Globalization.CultureInfo("zh-CN");
}
NBear.Web.UI.WebHelper.LoadResources("Strings");
}

    在GlobalizationDemo.aspx页面中,包含了一个DropDownList用于更换指定语言的资源,同时使用GetString()输出一个定义在资源文件中的Hello键值的文本资源。改变DropDownList中的语言选择,将可以看到,页面会显示取自不同的资源文件的文本资源。

    下面是页面的code hehind,页面载入时,设置当前的默认语言,并且在DropDownList的DropDownList1_SelectedIndexChanged事件处理中,在选择的语言变化时,修改载入的资源:

public partial class GlobalizationDemo : NBear.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
for (int i = 0; i < DropDownList1.Items.Count; i++)
{
ListItem item = DropDownList1.Items[i];
if (item.Value.ToLower() == NBear.Web.UI.WebHelper.DefaultCulture.ToString().ToLower())
{
DropDownList1.SelectedIndex = i;
}
}
}
}
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
NBear.Web.UI.WebHelper.DefaultCulture = new CultureInfo(DropDownList1.SelectedValue);
NBear.Web.UI.WebHelper.LoadResources("Strings");
}
}

    那么这些资源在哪里定义的呢?

    在ASP.NET 2.0下,资源文件一般需要定义在App_GlobalResources特别目录中,当然实际上定义在别处也没关系。我们的示例中,在这个目录下定义了两个resx文件Strings.en-US.resx和Strings.zh-CN.resx。分别对应中英文两个语言。这两个文件中都只包含了一个Hello键值及对应的文本内容。

    另外,App_GlobalResources目录中还包含了一个ResGen.cmd文件,这是一个批处理脚本,它用于简化将resx编译为.resources文件到bin目录。必须将resx文件编译为bin目录下的.resources文件,才能被框架访问到。ResGen.cmd文件的内容如下:

@echo off
"C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\resgen.exe" Strings.en-US.resx ..\bin\Strings.en-US.resources
"C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\resgen.exe" Strings.zh-CN.resx ..\bin\Strings.zh-CN.resources

    注意,如果要修改或添加资源项目,只需要修改resx文件,并重新点击ResGen.cmd编译资源文件即可,不需重新编译整个网站程序。

AjaxHelper

    AjaxHelper源自Teddy以前的一个同名Ajax框架。原来的实现基于对prototype这个开源Ajax实现的封装,实现了ASP.NET下基于UserControl实现各种Ajax效果的功能。自动ASP.NET 2.0发布以后,Teddy已经将AjaxHelper完美集成到NBear中的扩展页面基类中,并且使用ASP.NET 2.0内置的Callback机制代替原来的prototype依赖。

    集成到NBear使得基于这个集成本版的AjaxHelper的使用更简单优雅。

    示例代码中的AjaxDemo.aspx和AjaxDemo2.aspx这两个页面演示了集成到Page基类的Ajax功能的使用。

    NBear中目前这个AjaxHelper支持两中使用模式。

    模式一,不支持浏览器刷新模式。

    所谓不支持浏览器刷新指的是,在打开页面,并以该模式执行了某些Ajax效果后,如果点击浏览器的刷新按钮,或者按F5,页面状态会回复到初始载入状态。

    AjaxDemo.aspx页面演示了该模式的Ajax回调的使用。

    首先,只要使用AjaxHelper效果的页面,必须重载EnableAjaxCallback属性,并返回true,否则,页面生成的代码不会带有用于Ajax回调的支持脚本,所有的Ajax效果都不会生效。可以在code behind中,象下面这样重载EnableAjaxCallback属性: public partial class AjaxDemo : NBear.Web.UI.Page
{
protected override bool EnableAjaxCallback
{
get
{
return true;
}
}
}
    再来看AjaxDemo.aspx页面的内容: <%@ Page Language="C#" AutoEventWireup="true" CodeFile="AjaxDemo.aspx.cs" Inherits="AjaxDemo" %>
<!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>Untitled Page</title>
<script language="javascript" type="text/javascript">
function customFunc(data)
{
alert(data);
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<input type="button" value="Test Callback" onclick="<%= Ajax.Callback("AjaxTemplates/Simple", null, "customFunc") %>" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<input type="button" value="Test Update" onclick="<%= Ajax.Update("AjaxTemplates/DataBinding", "outputElementId", "num=5", "customFunc") %>" />
<br />
<br />
<div id="outputElementId"></div>
</div>
</form>
</body>
</html> 
    注意,页面中定义了两个按钮,它们的onclick事件处理包含了Ajax调用代码。 Ajax.Callback(string ajaxTemplate, string parms, string onComplete)
    - 该方法将会执行一个对指定的ajaxTemplate的回调,可以通过parms传递形如"paramName1=1&paramName2=2"这样的类似QueryString的参数,第三个参数onComplete是一个用于对回调返回的内容进行处理的客户端脚本函数的名称。 Ajax.Update(string ajaxTemplate, string outputElementId, string parms, string onComplete)

    - 该方法和Ajax.Callback的区别是,它多了一个参数outputElementId,可以指定一个包含innerHTML属性的标签(如div,span等)的Id,回调成功的内容在交给onComlpete前,会被自动替换到outputElementId指定的标签的innerHTML属性内容。当然,也可以不指定onComplete参数,传递一个null就行。

    页面中Ajax.Callback和Ajax.Update分别调用了两个AjaxTemplate:Simple和DataBinding。这两个AjaxTemplate实际上是两个特殊的UserControl,它们定于AjaxTemplates目录中。

    所有的用作AjaxTemplate的User Control必须从NBear.Web.UI.AjaxTemplate类继承。并且,如果要对页面面内容进行code behind的处理,如进行数据绑定,不能在Page_Load中进行处理,而必须重载OnAjaxTemplatePreRender()方法进行处理。Page_Load中的代码永远不会被执行。

    下面简单列举Simple和DataBinding的代码。

    注意Simple只在包含ascx页面包含了一个简单文本,不包含任何有效code behind代码:

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="Simple.ascx.cs" Inherits="AjaxTemplates_Simple" %>
Hello Simple!

    DataBinding在ascx页面包含了一个空的GridView控件如下:

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="DataBinding.ascx.cs" Inherits="AjaxTemplates_DataBinding" %>
<asp:GridView ID="GridView1" runat="server">
</asp:GridView>

 

    同时DataBinding.ascx.cs这个code behind文件中,对GridView1绑定了一些数据,注意,我们重载了OnAjaxTemplatePreRender函数来执行绑定。另外,你可以看到,我们从OnAjaxTemplatePreRender的callbackParams参数中获得了从AjaxDemo.aspx页面的Button2传递过来的num参数。

public partial class AjaxTemplates_DataBinding : NBear.Web.UI.AjaxTemplate
{
private SampleEntity[] objs = null;
private void LoadSampleEntities(int num)
{
objs = new SampleEntity[num];
for (int i = 0; i < num; i++)
{
objs[i] = EntityFactory<SampleEntity>.CreateObject();
objs[i].ID = i + 1;
objs[i].Name = Guid.NewGuid().ToString();
}
}
public override void OnAjaxTemplatePreRender(System.Collections.Generic.Dictionary<string, string> callbackParams)
{
LoadSampleEntities(int.Parse(callbackParams["num"]));
GridView1.DataSource = objs;
GridView1.DataBind();
}

 模式二,支持浏览器刷新模式。

    相对于模式一,采用模式二时,浏览器刷新时,之前的最后一次Ajax回调能够被记忆,并在页面载入后自动重新执行。

    AjaxDemo2.aspx演示了采用模式二使用AjaxHelper的功能。

注意,AjaxDemo2.aspx和AjaxDemo.aspx的唯一不同只在于aspx文件,参见下面的AjaxDemo2.aspx的代码: <%@ Page Language="C#" AutoEventWireup="true" CodeFile="AjaxDemo2.aspx.cs" Inherits="AjaxDemo2" %>
<!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 id="Head1" runat="server">
<title>Untitled Page</title>
<script language="javascript" type="text/javascript">
function customFunc(data)
{
alert(data);
}
</script>
</head>
<body onload="<%= Ajax.OnPageLoad() %>">
<form id="form1" runat="server">
<div>
<input type="button" value="Test Callback" onclick="<%= Ajax.Callback2("AjaxTemplates/Simple", null, "customFunc") %>" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<input type="button" value="Test Update" onclick="<%= Ajax.Update2("AjaxTemplates/DataBinding", "outputElementId", "num=5", "customFunc") %>" />
<br />
<br />
<div id="outputElementId"></div>
</div>
</form>
</body>
</html> 
    和AjaxDemo.aspx页面比较,您可以发现两点细微的区别,请注意粗体的代码。

    第一点不同是,页面的body标签多了一个onload事件处理,这个事件处理的代码的作用就是在页面loaded之后,自动重新执行上一次模式二方式执行的Ajax回调。

    第二点不同是,此时使用Ajax.Callback2和代替了模式一中的AjaxUpdate2,他们的参数列表和含义完全相同。

    如果运行AjaxDemo2.aspx页面,并点击按钮,您就会发现,在点击按钮的同时,页面的地址栏部分会被附加一个#...的代码,这里就包含了上一次Ajax.Callback2或Ajax.Update2执行时的所有参数。Ajax.OnPageLoad()就是根据这些参数来重新执行上一次Ajax回调的。

    实际上,模式一和模式二完全可以在同一个页面混合使用,只需记住,只有Ajax.Callback2或Ajax.Update2执行的上一次(仅仅一次,在之前的Ajax回调是不记忆的)Ajax回调可以在页面刷新时被自动重复执行

本文作者:



相关阅读:
javascript XMLHttpRequest对象全面剖析
20个有用的PHP+jQuery组件和教程(英文)
通过避免下列10个常见ASP.NET缺陷使网站平稳运行下
第十四节--命名空间
JavaScript 小型打飞机游戏实现原理说明
ASP读取Request.QueryString编码的函数代码
js function使用心得
关于JavaScript 的事件综合分析
Win XP远程控制时如何保证安全
SQL命令大全-中英文对照
MySQL中文参考手册--连接与断开服务者
从MySQL得到最大的性能
CSS教程:制作圆角矩形的网站头像
IE漏洞攻击剧增 最新/CSS/c.js木马防范手记
快速导航

Copyright © 2016 phpStudy | 皖ICP备18014864号-4