上周由于项目的需求要动态加载Treeview数据.数据大概有10000Rows ,同时一次Loading界面容易出现假死现象,在网上找了些多解决方案,最后决定使用AJAX技术.现把使用过程中遇到的问题和需要注意的事项总结如下,
    环境:VS.NET2003 +SQL2000
    使用DLL:BorgWorX.Web.Core.Ajax.dll(这是网上download的一个封装好了DLL,具体的下载网址不记得了,如果需要可以留下Email,PS自己下).
    (一)web.config配置:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
   
  <system.web>
 <httpHandlers>
    <!--<add verb="POST,GET" path="ajax/*.ashx" type="BorgWorX.Web.Core.Ajax.PageHandlerFactory, Ajax" />-->
    <add verb="POST,GET" path="ajax/*.ashx" type="BorgWorX.Web.Core.Ajax.PageHandlerFactory, BorgWorX.Web.Core.Ajax" />
    </httpHandlers> 

    <!--  动态调试编译
          设置 compilation debug="true" 以启用 ASPX 调试。否则,将此值设置为
          false 将提高此应用程序的运行时性能。
          设置 compilation debug="true" 以将调试符号(.pdb 信息)
          插入到编译页中。因为这将创建执行起来
          较慢的大文件,所以应该只在调试时将此值设置为 true,而在所有其他时候都设置为
          false。有关更多信息,请参考有关
          调试 ASP.NET 文件的文档。
    -->
   
    <compilation defaultLanguage="c#" debug="true"></compilation>

    <!--  自定义错误信息
          设置 customErrors mode="On" 或 "RemoteOnly" 以启用自定义错误信息,或设置为 "Off" 以禁用自定义错误信息。
          为每个要处理的错误添加 <error> 标记。

          "On" 始终显示自定义(友好的)信息。
          "Off" 始终显示详细的 ASP.NET 错误信息。
          "RemoteOnly" 只对不在本地 Web 服务器上运行的
           用户显示自定义(友好的)信息。出于安全目的,建议使用此设置,以便
           不向远程客户端显示应用程序的详细信息。
    -->
    <customErrors defaultRedirect="Error.aspx" mode="Off"/>

    <!--  身份验证
          此节设置应用程序的身份验证策略。可能的模式是 "Windows"、
          "Forms"、 "Passport" 和 "None"

          "None" 不执行身份验证。
          "Windows" IIS 根据应用程序的设置执行身份验证
            (基本、简要或集成 Windows)。在 IIS 中必须禁用匿名访问。
          "Forms" 您为用户提供一个输入凭据的自定义窗体(Web 页),然后
           在您的应用程序中验证他们的身份。用户凭据标记存储在 Cookie 中。
          "Passport" 身份验证是通过 Microsoft 的集中身份验证服务执行的,
           它为成员站点提供单独登录和核心配置文件服务。
    -->
    <authentication mode="Forms">
 
       <forms name="ManageAuth" loginUrl="Login.aspx" protection="All" path="/"/>
   
    </authentication>

 <!--  授权
           此节设置应用程序的授权策略。可以允许或拒绝不同的用户或角色访问
          应用程序资源。通配符: "*" 表示任何人,"?" 表示匿名
          (未经身份验证的)用户。
    -->

    <authorization>
         <allow users="*" />  <!-- 允许所有用户 -->
            <!--  <allow     users="[逗号分隔的用户列表]"
                             roles="[逗号分隔的角色列表]"/>
                  <deny      users="[逗号分隔的用户列表]"
                             roles="[逗号分隔的角色列表]"/>
            -->
    </authorization>

    <!--  应用程序级别跟踪记录
          应用程序级别跟踪为应用程序中的每一页启用跟踪日志输出。
          设置 trace enabled="true" 可以启用应用程序跟踪记录。如果 pageOutput="true",则
          在每一页的底部显示跟踪信息。否则,可以通过浏览 Web 应用程序
           根目录中的 "trace.axd" 页来查看
          应用程序跟踪日志。
    -->
    <trace enabled="false" requestLimit="10" pageOutput="false" traceMode="SortByTime" localOnly="true"/>

    <!--  会话状态设置
          默认情况下,ASP.NET 使用 Cookie 来标识哪些请求属于特定的会话。
          如果 Cookie 不可用,则可以通过将会话标识符添加到 URL 来跟踪会话。
         若要禁用 Cookie,请设置 sessionState cookieless="true"。
    -->
    <sessionState mode="InProc" stateConnectionString="tcpip=127.0.0.1:42424" sqlConnectionString="data source=127.0.0.1;Trusted_Connection=yes" cookieless="false" timeout="240"/>

    <!--  全球化
          此节设置应用程序的全球化设置。
    -->
    <globalization requestEncoding="gb2312" responseEncoding="gb2312"/>
  
   <!-- 文件上传大小设置
   
  -->
   <httpRuntime executionTimeout="1000" maxRequestLength="102400" useFullyQualifiedRedirectUrl="false"/>

 </system.web>


<appSettings>
  <add key="Anp.Refill.SQLServerConnStr" value="uid=sa;password=qdkzcz;database=GZ_Voucher;data source=192.168.1.88"/>
  <add key="Anp.Refill.WebDAL" value="Anp.Refill.SQLServerDAL"/>
  <add key="Anp.Refill.MaxExportSize" value="10000"/>
  <add key="Anp.Refill.PerPageSize" value="2000"/>
</appSettings>

</configuration>

红色的字体为使用AJAX加入的httpHandlers属性,其他为我们项目配置.

    (二)前台设计:
    在<head></head>中加入sricpt代码:
     
     

 <script language="javascript">
   
                 var Index;
                 function ds()
                 { 
                       ChannelTree.GetChannelChild(ChannelsTreeView.getTreeNode(Index).getAttribute("ID"),returnDs_callback);
                 }

                
                 function returnDs_callback(response)
                 {
                      var n=ChannelsTreeView.getTreeNode(Index);
                      var load=n.getChildren();
     if(load.length!=1)
     {
      //去处loading标签
         for(i=0;i<load.length;i++)
       {
        var cNode;
        cNode=load[i];
        if (cNode.getAttribute("Text").indexOf("Loading...") !=-1)
        { 
          cNode.remove();
          break;
         }
       }
      return;//如果已经存在数据,那就不再读取。
     }
     else
     {
       var loadNode=load[0];
       loadNode.remove();
 
     }
     
                    var ds=response.value;
                    if(ds!=null && ds.Tables!=null && typeof(ds)=="object")
                    {
                       
                        for(var i=0;i<ds.Tables[0].Rows.length;i++)
                        {
                            var newNode=ChannelsTreeView.createTreeNode();

       newNode.setAttribute("ID",ds.Tables[0].Rows[i].ag_AgentId);
       newNode.setAttribute("Text",ds.Tables[0].Rows[i].ag_AgentName);
       newNode.setAttribute("NavigateUrl","ShowChannel.aspx?ChannelID=" +newNode.getAttribute("ID")+"");
       newNode.setAttribute("Target","viewframe");
                            if(newNode.getAttribute("ID")!=null)
       {
        var loadNode=ChannelsTreeView.createTreeNode();
        loadNode.setAttribute("Text","Loading...");
        //loadNode.setAttribute("ID","-2");
        newNode.add(loadNode);
       }
                            n.add(newNode);
                        }
                    }
                    else
                    {
      alert(response.error);
                    }
                 }
  </script>
  <script language="javascript" event="onexpand" for="ChannelsTreeView">
            //TODO:在此处填写TreeView的OnExpand事件的代码。
          //  alert("sucess");
     Index= window.event.treeNodeIndex;//获得展开的节点的位置,根节点为0。
    if(Index=='0')return;//如果是根节点的话就直接返回。
    ds();
    
  </script>

    <body></body>中加入如下脚本:
     <!--中间-->
      <TABLE id="Table1" cellSpacing="0" cellPadding="0" width="100%" border="0">
       <TR>
        <TD vAlign="top" width="25%"><FONT face="宋体"><frameset frameBorder="0" frameSpacing="0" border="0" rows="100%"         borderColor="whitesmoke"><iewc:treeview id="ChannelsTreeView" runat="server" Width="100%" Target="mainframe" SelectedImageUrl="../Images/tree_file.gif"
            ImageUrl="../Images/tree_folder.gif" ExpandedImageUrl="../Images/tree_folderopen.gif" BackColor="WhiteSmoke" BorderColor="IndianRed" ShowLines="False" SelectExpands="True" EnableViewState="False"></iewc:treeview></FONT></FRAMESET></TD>
        <TD vAlign="top" width="75%"><iframe id="viewframe" name="viewframe" align="top" frameBorder="no" width="100%" scrolling="no"
          height="600"></iframe>
        </TD>
       </TR>
      </TABLE>
      <!--中间--></TD>

    (三)后台代码:
     1.首先在 private void Page_Load(object sender, System.EventArgs e)函数中注册下
       BorgWorX.Web.Core.Ajax.Utility.RegisterTypeForAjax(typeof(ChannelTree));
     2.编写获取动态数据的函数
        
      [BorgWorX.Web.Core.Ajax.AjaxMethod()]
      public DataSet GetChannelChild(string parentId)
      {
       DataSet ds = null;
       Agent agentBll =new Agent();
       SearchAgentInfo searchInfo = new SearchAgentInfo();
       searchInfo.ParentAgent = parentId;
       ds = agentBll.FindAgentList4(searchInfo);
       return ds;
      }

      (四)涉及的数据表结构:
        

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[db_Agent]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[db_Agent]
GO

CREATE TABLE [dbo].[db_Agent] (
 [ag_AgentID] [varchar] (20) COLLATE Chinese_PRC_CI_AS NOT NULL ,
 [ag_AgentName] [varchar] (50) COLLATE Chinese_PRC_CI_AS NULL ,
 [ag_ParentID] [varchar] (20) COLLATE Chinese_PRC_CI_AS NOT NULL ,
 [ag_AgentType] [int] NOT NULL ,
 [ag_NodeLvl] [int] NOT NULL ,
 [ag_NodeCode] [varchar] (30) COLLATE Chinese_PRC_CI_AS NOT NULL ,
 [ag_AgentPWD] [varchar] (50) COLLATE Chinese_PRC_CI_AS NULL ,
 [ag_AgentPWD2] [varchar] (50) COLLATE Chinese_PRC_CI_AS NULL ,
 [ag_UserLevel] [int] NULL ,
 [ag_Commision] [int] NULL ,
 [ag_BackMode] [int] NOT NULL ,
 [ag_Register] [varchar] (30) COLLATE Chinese_PRC_CI_AS NULL ,
 [ag_IDCard] [varchar] (20) COLLATE Chinese_PRC_CI_AS NULL ,
 [ag_Address] [varchar] (100) COLLATE Chinese_PRC_CI_AS NULL ,
 [ag_ContactTel] [varchar] (30) COLLATE Chinese_PRC_CI_AS NULL ,
 [ag_BankCode] [varchar] (10) COLLATE Chinese_PRC_CI_AS NULL ,
 [ag_BankAccountNo] [varchar] (50) COLLATE Chinese_PRC_CI_AS NULL ,
 [ag_CreateDate] [datetime] NULL ,
 [ag_CreateBy] [varchar] (50) COLLATE Chinese_PRC_CI_AS NULL ,
 [ag_MarketingAgent] [varchar] (50) COLLATE Chinese_PRC_CI_AS NULL ,
 [ag_AgreeNo] [varchar] (100) COLLATE Chinese_PRC_CI_AS NULL ,
 [ag_Status] [int] NOT NULL ,
 [ag_Enter_flag] [int] NULL ,
 [ag_Enter_code] [varchar] (20) COLLATE Chinese_PRC_CI_AS NULL
) ON [PRIMARY]
GO

        (五):开发过程中的问题和注意点:
        1.AJAX一定要注册,包括web.config和LOAD里的设置.
        2.script脚本要编写正确,不要抛出太多UNDEFINED错误,这里推荐一款javascript的编辑器给大家:Aptana Studio,大家可以去下来玩玩,自己感觉不错,还有script中都设些ALERT的,可以观察程序的流程.
        3.最后还是代码完整,健壮性.