• 在不用UpdatePanel的情形下可与ASP.NET AJAX 使用的酷UI模板技术


    【原文地址】Tip/Trick: Cool UI Templating Technique to use with ASP.NET AJAX for non-UpdatePanel scenarios
    【原文发表日期】 Sunday, October 22, 2006 9:02 PM

    这个周末我一直饶有兴趣地在玩ASP.NET AJAX Beta版

    通常情形下,当我把AJAX功能集成进我的编码时,我最后总是使用 ASP.NET AJAX 提供的内置服务器端控件(譬如UpdatePanel和UpdateProgress等)以及ASP.NET AJAX控件工具包里的那些酷控件。Scott Hanselman 两个星期前在他最近的一次 podcast 中采访我时开玩笑地声称,使用这些AJAX控件简直是“作弊(cheating)”, 因为在大多数常见的情形下,它们不需要你写任何的客户端JavaScript编码。

    这个周末,我决定把我的编程集中在 ASP.NET AJAX 框架中根本不使用UpdatePanel的一些客户端JavaScript 库函数上,试验另外的方式用服务器来轻松地产生HTML UI,然后把这些HTML通过AJAX动态地注入页面内。在这个过程中,我建立了一个我认为是比较有用的库,这个库可以和ASP.NET AJAX 以及其他 AJAX 库一起使用,来提供一个很好的ASP.NET模板UI机制,它不使用也不需要象 postback 和 viewstate 这样的概念,但仍旧提供了控件封装和简易重用的好处。

    首先,ASP.NET AJAX中JavaScript 网络层(Networking Stack)的一些简短的背景知识

    在开始讨论我上面提到的模板方法之前,先提供一些ASP.NET AJAX中客户端JavaScript库方面的背景知识,让我们首先来创建一个简单的AJAX "hello world" 应用。这个应用允许用户输入一个名字,点击一个按钮,然后在客户端使用JavaScript向服务器做一个AJAX调用,进而输出一个消息:

    ASP.NET AJAX 包含了一个非常灵活的JavaScript 网络库 (network library stack),对.NET 数据类型有着丰富的序列化支持。你可以在服务器端定义可从客户端JavaScript 里调用的方法,要么是你的 ASP.NET 页面类里的静态方法,要么给你的ASP.NET应用添加一个web服务,这个服务须饰以 [Microsoft.Web.Script.Services.ScriptService] 元数据属性,而呈示的方法则须饰以标准的 [WebMethod] 属性。

    例如,下面是个SimpleService.asmx web服务,内含一个GetMessage方法,该方法接受一个字符串参数:

    using System;
    using 
    System.Web.Services;

    [Microsoft.Web.Script.Services.ScriptService]
    public class SimpleService : WebService {

        [WebMethod]
        
    public string GetMessage(string name) {
            
    return "Hello <strong>" + name + "</strong>, the time here is: " + DateTime.Now.ToShortTimeString();
        
    }
    }

    ASP.NET AJAX 然后可以自动创建一个JavaScript代理类,可在客户端用来调用这个方法,以及传递合适的参数。添加这个JavaScript代理类最容易的方法是在页面上添加一个 <asp:ScriptManager> 控件,然后指向web服务的端点。(这个控件同时也确保每个库在页面只被加载一次。)

    然后我就可以调用这个方法,把文本框里的值传给它,用象下面这样的客户端 JavaScript 编码设置好一个回调事件处理器,定在服务器响应时触发。注:我可以把 JavaScript 编码写得更加花哨,去掉其中的几行代码,但我目前是故意要保持清晰和简单,以避免故弄玄虚:

    <html>
    <head id="Head1" runat="server">
        
    <title>Hello World Service</title>
        
    <link href="StyleSheet.css" rel="stylesheet" type="text/css" />
        
        <
    script language="javascript" type="text/javascript">
            
            
    function callServer() {
                SimpleService.GetMessage( $
    get("Name").value, displayMessageCallback );
            
    }
        
            
    function displayMessageCallback(result) {
                $
    get("message").innerHTML result;
            
    }
        
        
    </script>
                    
    </head>
    <body>
        
    <form id="form1" runat="server">
            
            
    <asp:ScriptManager ID="ScriptManager1" runat="server" >
                
    <Services>
                    
    <asp:ServiceReference Path="~/SimpleService.asmx" />
                </
    Services>
            
    </asp:ScriptManager>
            
            
    <h1>Hello World Example</h1>
            
            
    <div>
                Enter Name: 
    <input id="Name" type="text" />
                
                <
    a href="BLOCKED SCRIPTcallServer()">Call Server</a>

                
    <div id="message"></div>
            
    </div>
            
        
    </form>
    </body>
    </html>

    这样,当我运行这个页面,输入一个名字,Scott,页面就会使用AJAX 回调,动态更新页面上的HTML,而不需要任何postback或页面更新。

    使用模板产生HTML的一个比较干净的的做法

    你可以从上面的例子看出,我可以很轻松地从服务器端返回HTML,在客户端把它注入页面。但是,我的这个做法的一个缺点是,我把生成HTML的逻辑直接参杂到我的服务器web method里了。这个做法不好,因为,1) 混杂了UI和逻辑编码,2) 随着 UI 愈加丰富,编码将会变得难以维护和编写。

    我想要的是一个简易的方法,在我的web service方法里执行我的逻辑,获取数据,然后把数据传给某个模板或视图类来生成要返回的 HTML UI 结果。譬如,考虑生成一个客户/订单管理的应用,在其中使用AJAX来生成类似这样的一个客户列表UI:

    我想要在我的 WebService 里编写象下面这样的服务器端编码来按国家查询客户,然后返回一个合适的HTML列表UI。注意到下面的ViewManager.RenderView 方法是如何允许我传进一个数据对象来绑定UI的。所有的UI生成编码都移出了我的控制器webmethod,都封装在我的View里了:

        [WebMethod]
        
    public string GetCustomersByCountry(string country)
        {
            CustomerCollection customers
    DataContext.GetCustomersByCountry(country);

            if 
    (customers.Count > 0)
                
    return ViewManager.RenderView("customers.ascx", customers);
            else
                return 
    ViewManager.RenderView("nocustomersfound.ascx");
        
    }

    结果是,这并不是很难,只需要20行左右的代码就实现了 ViewManager 类和上面用到的 RenderView 方法。你可以在这里下载这个简单的实现

    我的实现允许你使用标准的ASP.NET 用户控件 (.ascx 文件)模型来定义一个显示模板,这意味著你拥有完全的VS设计器支持, intellisense,和编译检查。它并不要求你一定要用一个页面来包含这个用户控件,实际上,我的 RenderView 实现在显示时动态地生成一个空Page对象来包含这个用户控件,把显示记录下来,以一个字符串的形式返回。

    譬如,下面这个Customer.ascx模板,我可以用它来生成象上面那个截图里的客户列表输出。它生成了一串客户的名字,每个客户有一个连接,指向他们的订单历史细节:

    <%@ Control Language="C#" CodeFile="Customers.ascx.cs" Inherits="Customers" %>

    <div class="customers">

        
    <asp:Repeater ID="Repeater1" runat="server">
            
    <ItemTemplate>
            
                
    <div>    
                    
    <a href="BLOCKED SCRIPTCustomerService.GetOrdersByCustomer('<%# Eval("CustomerID") %>', displayOrders)">
                        
    <%# Eval("CompanyName") %>
                    
    </a>
                
    </div>

            
    </ItemTemplate>
        
    </asp:Repeater>

    </div>

    相关的后端代码是这样的(注,如果我想的话,我可以往里面添加特定视图的格式化方法):

    using System;

    public 
    partial class Customers : System.Web.UI.UserControl
    {
        
    public object Data;

        void 
    Page_Load(object sender, EventArgs e)
        {
            Repeater1.DataSource 
    Data;
            
    Repeater1.DataBind();
        
    }
    }

    为了把数据传进模板,(譬如,上面这个customers 集合),我一开始时要求每个UserControl 实现一个IViewTemplate 接口,通过它我可以将数据与UserControl 相关联。但玩了一阵后,我决定使用一个更简单的用户模型,让UserControl 呈示一个如上面所示的公开的Data属性。然后,ViewManager.RenderView 方法通过反射把传给它本身的数据对象与UserControl实例相关联,之后,UserControl的行为就象一个普通用户控件一样。

    最后得到的结果是一个非常强有力而且简易的方式,它可以生成你想要的任何类型的HTML回复,而且非常干净地封装在.ascx 模板文件里了。

    最后的加工

    你可以在这里下载我最后建立的样例的完整编码。为好玩,我给上面那个客户列表例子另添加了功能,在按国家查询返回客户列表后,用户可以点击任何一个客户的名字,然后就跳出一个相应客户的订单表(还有他们下订单的日期)。这也是用我上面描述的方法完全通过AJAX来实现的:

    整个应用在客户端只有8行JavaScript编码,在服务器端总共有15行编码(包括数据访问的所有代码)。所有的HTML UI生成编码是封装在4个.ascx模板文件里的,我可以从我的 webmethod 里按需加载这些模板文件并对其绑定我的数据:

    点击这里下载ViewManager.RenderView的编码,如果你想看看,试用一下的话。

    希望本文对你有所帮助,

    Scott


     

    修改后可运行的示例程序:AjaxSample

  • 相关阅读:
    C# WinForm程序中强制退出程序以及启动程序
    WinForm程序中对关闭按钮的操作
    DataTable转换为List
    json日期转换
    ajax局部刷新
    程序暂停或延迟几秒再次运行
    分页显示的制作流程
    Django 项目基础操作总结
    Django初识
    Mysql有关分页的操作
  • 原文地址:https://www.cnblogs.com/scgw/p/851301.html
Copyright © 2020-2023  润新知