65.9K
CodeProject 正在变化。 阅读更多。
Home

AJAX DataGrid

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.57/5 (21投票s)

2007年6月1日

4分钟阅读

viewsIcon

111871

downloadIcon

2018

本文演示了如何结合我上一篇文章中的 JavaScript DataGrid 来使用 AJAX 技术。

Screenshot - gridScreen.jpg

引言

AJAX(Asynchronous JavaScript and XML,异步 JavaScript 和 XML)不是一项技术,而是一种利用多项技术的技术。

  1. HTML 和 CSS 用于标记和样式化信息。
  2. Document Object Model (DOM),通过客户端脚本(主要是 ECMA 脚本实现,如 JavaScript 和 JScript)访问,用于显示和交互呈现的信息。
  3. XML 通常用作客户端和服务器之间传输数据的格式。但并非强制要求;即使是纯文本也可以用作数据格式。在某些情况下,也可以使用预格式化的 HTML、JSON、纯文本甚至 EBML。
  4. XMLhttpRequest 对象用于与服务器异步交换数据。在某些 AJAX 框架和某些情况下,会使用 IFrame 对象与服务器交换数据,而在其他情况下,则会使用动态添加的“script”标签。

如上所述,AJAX 本身并非一项技术。它类似于 DHTML,指的是一系列技术(标记语言(如 HTML)、客户端脚本语言(如 JavaScript)、演示文稿定义语言(Cascading Style Sheets, CSS)和 Document Object Model)。AJAX 的主要元素是 XMLhttpRequest,它允许浏览器向服务器发出动态异步请求,而无需重新加载页面。XmlHttpRequest 可以消除页面刷新的需求,并且在这种开发方法下,其他技术的使用和突出程度会更高。当使用 XMLHttpRequest 对象时,大量使用 JavaScript、CSS 和 DOM 会变得更加重要,并且它们会结合使用,以提供更高级的“单页”体验。其他技术之所以被包含在此术语中,是因为它们与用户体验相关,当与 XMLHttpRequest 结合使用时。

使用 AJAX 的原因

使用 AJAX 最明显的原因是改善用户体验。使用 AJAX 的页面比典型的网页更像独立的应用程序。单击导致整个页面重新加载的链接看起来是一种繁重操作。通过 AJAX,页面通常可以动态更新,从而更快地响应用户交互。一些人认为它将成为一项重要的技术,并将使 Web 比现在更好。

AJAX 的实现

在当前项目的示例中,我采用了 AJAX 开发方法来动态显示和交互呈现的信息。我决定结合我之前文章中的 JavaScript GridWeb Service。本文展示了如何在客户端简单地将我的 JavaScript Grid 与 AJAX 一起使用。由于客户端和服务器代码已经完成,我需要做的就是将它们整合到一个应用程序中。将 Grid 引入 Web 应用程序非常简单。我需要在客户端创建一个代理类来处理 Web Service。我创建了三个类:ProxyHelperCustomerProxyOrderProxyProxyHelper 类是一个实用类,CustomerProxyOrderProxy 类都使用此类向 Web Service 发送 SOAP 请求。

function ProxyHelper()
{
    var httpObj = new ActiveXObject("Microsoft.XMLHTTP");
    httpObj.onreadystatechange = onReadyStateChange;
    var thisRef = this;
    this.onDataLoaded;

    this.send = function(strRequest , soapAction, servicePath)
    {
       httpObj.open("POST", servicePath, true);
       httpObj.setRequestHeader("SOAPAction",soapAction );
       httpObj.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
       httpObj.send(strRequest);

    }

    function onReadyStateChange()
    {

         if(httpObj.readyState == 4)
         {
             if(httpObj.status == 200)
             {
               if(thisRef.onDataLoaded!=null)
               {
                 httpObj.responseXml.setProperty("SelectionLanguage", "XPath");
                 thisRef.onDataLoaded(httpObj.responseXml);

               }
             }
             else
             {
               alert("Status: "+httpObj.statusText+".\nResponseText: 
                        "+httpObj.responseText);
            }
         }
    }
}

customerProxyorderProxy 类都有两个事件:onDeserializedonXmlDataLoaded,它们在接收到 Web Service 的数据时触发。这些类还具有相应的 D方法来调用 Web Service 的方法,例如“CreateCustomerCreateOrderUpdateOrderGetCustomers 等”。这些 D方法具有与 Web Service 方法相同的签名。

当 XML 数据加载完成后,会触发 onXmlDataLoaded 事件,而当 XML 数据加载并反序列化为对象后,会触发 onDeserialized 事件。onXmlDataLoaded 的参数是 XMLDocument,而 onDeserialized 的参数是反序列化后的对象。

function CustomerProxy()
{
     var path = "../Server/Customer.asmx";
     var proxyHelper = new ProxyHelper();
     proxyHelper.onDataLoaded = onDeserialize;
     var thisRef = this;
     this.onDeserialized;
     this.onXmlDataLoaded;

     function onDeserialize(responseXml)
     {
        if(thisRef.onXmlDataLoaded!=null)
            thisRef.onXmlDataLoaded(responseXml);
        if(thisRef.onDeserialized==null)
          return;

        thisRef.onDeserialized(deserializeXML(responseXml));
     }

     this.getCustomers = function()
     {
        var soapRequest = "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
          soapRequest += "<soap:Envelope 
        xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ";
          soapRequest += " xmlns:xsd=\http://www.w3.org/2001/XMLSchema\ 
        xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"> ";
          soapRequest += " <soap:Body><GetCustomers 
        xmlns=\"http://tempuri.org/\" /></soap:Body></soap:Envelope>";

        proxyHelper.send(soapRequest,"http://tempuri.org/GetCustomers",path);
     }
  ...
 }

我在客户端编写了一个简单的实用函数 called "deserializeXML",它将 XML 转换为 JS 对象。

function deserializeXML(responseXml)
{
    var result =  responseXml.documentElement.selectSingleNode
                ("./child::*/child::*/child::*");
    if(result.firstChild==null)
        return emptyResponse;
    if(result.firstChild.nodeType==1)
    {
        var resultArray = new Array();
        for(var index = 0; index < result.childNodes.length; index++)
        {
            //convert the XML node into js object and add item to result array

            resultItem = result.childNodes[index];
            var customer = new Object();
            for(var index1 = 0; index1 < resultItem.childNodes.length; 
                                index1++)
            {
                customer[resultItem.childNodes[index1].nodeName] = 
                    resultItem.childNodes[index1].text;
            }
            resultArray.push(customer);
        }
        return resultArray;
    }
    else
        //return the result value without any serialization

        //as return value is supposed to be a primitive data type such as int,

        //boolean etc.

        return result.firstChild.nodeValue;
}

我在服务器端也采用了类似的方法,特别是在 XMLRepository 数据源上。我需要将传输对象保存到 XML 中。我编写了一个具有两个静态 D方法的实用类。

public class Serialization
{
    public static T FillObjectFromXMLDoc<T>(XmlDocument xmlDoc)
    {
        using (MemoryStream memoryStream = new MemoryStream())
        {
            StreamWriter streamWriter = new StreamWriter(memoryStream);
            streamWriter.Write(xmlDoc.OuterXml);
            streamWriter.Flush();
            XmlSerializer serilazer = new XmlSerializer(typeof(T));
            memoryStream.Position = 0;
            T obj = (T)serilazer.Deserialize(memoryStream);
            return obj;
        }
    }
    public static XmlDocument FillXmlDocFromObject<T>(T obj)
    {
        using (MemoryStream memoryStream = new MemoryStream())
        {
            StreamReader streamReader = new StreamReader(memoryStream);
            XmlSerializer serilazer = new XmlSerializer(typeof(T));
            serilazer.Serialize(memoryStream,obj);
            memoryStream.Position = 0;
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.LoadXml(streamReader.ReadToEnd());
            return xmlDoc;
        }
    }
}

使用代理类

function onGridCustomerUpdated(rowItem)
{
    var customerProxy = new  CustomerProxy();
    customerProxy.onDeserialized = onServerCustomerUpdated;
    customerProxy.onXmlDataLoaded = onShowResponseXml;
    customerProxy.updateCustomer(rowItem.id,rowItem["Company Name"],
        rowItem["Contact Name"], rowItem["Contact Title"], 
        rowItem["Address"] , rowItem["City"],rowItem["Region"],
                rowItem["Postal Code"], rowItem["Country"] , 
        rowItem["Phone"] , rowItem["Fax"]);
}

function onServerCustomerUpdated(result)
{
    if(result!="true")
    alert("Failure to save the data.");
} 

onGridCustomerUpdatedgrid.onRowUpdated 事件的处理程序。您可以在 Grid 的文章中找到关于 Grid 事件模型的所有信息。

链接

注意

请不要直接在您的项目中原封不动地使用此代码。这只是一个处理数据的演示版本,需要经过充分的测试。

如果您觉得这篇文章有趣,请为我投票。

© . All rights reserved.