NBearV3教程——Web篇

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

内容目录

1、Helper Methods - 辅助Web常用方法
2、ClientScriptFactory - 辅助生成客户端JS脚本
3、LoadResources()/GetString() - 多语言支持
4、AjaxHelper - 基于UserControl的AjaxHelper集成

从SF.NET下载NBear最新版本程序集、源码及使用教程

0、重要说明

本文讨论的内容只涉及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继承相应的基类即可。

1、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()。这组方法帮助进行常见的字符串转换。执行示例页面可以看到其中两个方法的演示,这里就不列举了。

2、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")));

3、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编译资源文件即可,不需重新编译整个网站程序。

4、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<stringstring> 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回调可以在页面刷新时被自动重复执行。


//本文结束

posted @ 2006-11-07 22:53  Teddy's Knowledge Base  Views(7087)  Comments(7Edit  收藏  举报