我做这5个实验都是一个一个来的,从一到五,没有跳跃也不敢跳跃啊!呵呵。
在这个练习里面我们将创建一个asp.net web服务从一个文本文件里面获得数据且把他返回给客户端脚本。然后这客户端脚本把这些数据呈递给一个自动完成的dropdown。
1,我们先来创建一个web 服务。在解决方案管理器俩面,右击web站点,选add new item。在弹出的对话框里面,选择web service,把他取名为AutoCompleteService.asmx, 且去掉Place code in separate file前面的小勾啊,这样的话他就不会生成代码后置类文件了。
2,我们手动去给这个asmx文件添加名字空间,且添加个system的引用,当然,在这个例子中还要添加其他的几个名字空间的引用,我们还要杀掉已经存在的自动生成的HelloWorld方法及与他关联的[WebMethod]属性。这个vs2005怎么就不能够象vs2003一样自动生成名字空间么?真是很郁闷,只是我的版本是beta2的,不知道正式版会是这样么?如果不能够自动生成名字空间就太残忍拉~还要在<%@ WebService指令行的class属性里写完整的包含名字空间的类名,代码如下:

<%@ WebService Language="C#" Class="Samples.AspNet.AutoCompleteService" %>
using System;
using System.IO;
using System.Web;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml.Serialization;

namespace Samples.AspNet
{
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    public class AutoCompleteService : System.Web.Services.WebService
    {

    }
}

 2, 在类文件里面,定义一个private的string类型的数组,语法如下:
private static string[] autoCompleteWordList = null;
我们再写个GetWordList方法,大家不要忘记在方法上面加[WebMethod]属性
具体写好后的代码如下:

<%@ WebService Language="C#" Class="Samples.AspNet.AutoCompleteService" %>

using System;
using System.IO;
using System.Web;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml.Serialization;

namespace Samples.AspNet
{
  [WebService(Namespace = "http://tempuri.org/")]
  [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
  public class AutoCompleteService  : System.Web.Services.WebService
  {
    private static string[] autoCompleteWordList = null;

    [WebMethod]
    public String[] GetWordList(string prefixText, int count)
    {    
      if (autoCompleteWordList == null)
      {
          //初始化个List泛型对象
          List<String> words = new List<string>();
          //初始化个文件另FileStream对象FileMode是Open,FileAccess是Read
          FileStream file = new
            FileStream(Server.MapPath("~/App_Data/words.txt"), FileMode.Open,
            FileAccess.Read);
          //初始化个StreamReader对象,用来读取文件流中的文本,这里我们可以不写上面的代码而直接让StreamReader来读取文本文件
          StreamReader reader = new StreamReader(file);
          String word;
          //循环一行一行读取文本数据
          while ((word = reader.ReadLine()) != null)
          {
             words.Add(word);//把每行数据添加到泛型对象中
          }
          file.Close();//关闭文件流
          autoCompleteWordList = words.ToArray();//把泛型对象转换成数组
          //把得到的那个数组排序
          Array.Sort(autoCompleteWordList, new CaseInsensitiveComparer());
      }
       //从刚刚那个数组中查找传递来的前缀字符
      int index = Array.BinarySearch(autoCompleteWordList, prefixText,
        new CaseInsensitiveComparer());
      if (index < 0)
      {
        index = ~index;//这话我从来没有见过,晕死不懂
      }

      int matchingCount;
      for (matchingCount = 0;
           matchingCount < count && index + matchingCount <
           autoCompleteWordList.Length;
           matchingCount++)
      {
        if (!autoCompleteWordList[index +
          matchingCount].StartsWith(prefixText,
          StringComparison.CurrentCultureIgnoreCase))
        {
          break;
        }
      }

      String[] returnValue = new string[matchingCount];
      if (matchingCount > 0)
      {
        Array.Copy(autoCompleteWordList, index, returnValue, 0,
          matchingCount);
      }
      return returnValue;
    }
     
  }
}
在GetWordList方法中我们要注意几点:
1,如果你想让你的web service里的方法能够被外部访问那么[WebMethod]属性是必须要有的
2,GetWordList方法有两个参数,第一个参数prefixText指用户最初输入在ui里的几个字符,这是将被自动完成的文本。count参数说明将有多少个选项将会显示在UI上。
3,在这个实验里面自动完成的数据来自于一个文本文件,当然,数据也能够来自于数据库以及任何数据源包括web service


练习2:使用Atlas脚本库来创建个自动完成的文本框
在这个联系里面我们将基于Default.master也就是我们以前的实验创建的master页创建一个内容content页。这个内容页类似于我们第一个实验创建的那个页面,他也包含了相同的search来call我们在第一个实验里面创建在web service里面的HelloWorld方法。你在这个实验中创建的content页面将论证一些重要的Atlas概念。他将引导你去创建一个有自动完成功能的文本框当用户在这文本框中进行输入的时候。Auto-completion是一个被定义在Atlas脚本库中的行为,这中行为还能够添加到任何及任意多的客户端界面元素。下面我们来创建一个content页面。
右击Default.master,选add content page.把这个内容页重新命名为Autocomplete.aspx.在代码视图中杀掉那两个ContentPlaceHolderId值不是Main的<asp:content>元素。在<%@ Page指令行设置Title属性为“第三个实验”.
在<asp:content>标记里面添加如下代码:
 

<form action="">

  <div>

    Search for

    <input id="SearchKey" type="text" />

    <input id="SearchButton" type="button" value="Search"

      onclick="DoSearch()"/>

  </div>

</form>

<div id="completionList"></div>

<hr style="width: 300px" />

<div>

  <span id="Results"></span>

</div>


我们再写一些脚本去调用web service。在最后一个<div>标记后面,我们写个<script>来调用我们在实验里创建的那个web service。也就是HelloWorldService.asmx.
 

<script type="text/javascript" src="HelloWorldService.asmx/js">

</script>
好了,我们再写一些脚本以便单击search按钮的时候能够调用上面那个web service里面的HelloWorld方法,代码如下,其实这些代码就是我们在实验里面写过的。
 

<script type="text/javascript">

 

  function DoSearch()

  {

    var SrchElem = document.getElementById("SearchKey");

    Samples.AspNet.HelloWorldService.HelloWorld(SrchElem.value,

      OnRequestComplete);

  }

 

  function OnRequestComplete(result)

  {

    var RsltElem = document.getElementById("Results");

    RsltElem.innerHTML = result;

  }
</script>
好了,search按钮的功能完成了,我们现在来为自动完成文本框搞个Atlas宣告块。
 

<script type="text/xml-script">

  <page xmlns:script="http://schemas.microsoft.com/xml-script/2005">

    <references>

    </references>

    <components>

    </components>

  </page>

</script>
这些代码我们在实验2里面见过了,注意根元素是page,还有个名字空间,在<references>标记里面放js引用,在<components>标记里面放一些Atlas客户端界面组件罢了。写好的代码如下:

<%@ Page Language="C#" MasterPageFile="~/Default.master" Title="Atlas实验3" %>
<asp:Content ID="Content3" ContentPlaceHolderID="Main" Runat="Server">

  <form action="">
    <div>
      Search for
      <input id="SearchKey" type="text" />&nbsp;
      <input id="SearchButton" type="button" value="Search"
        onclick="DoSearch()"/>
    </div>
  </form>

  <div id="completionList"></div>
  <hr style="width: 300px"/>
  <div>
    <span id="Results"></span>
  </div>
 
  <script type="text/javascript" src="HelloWorldService.asmx/js">
  </script>
   
  <script type="text/javascript">

  function DoSearch()
  {
    var SrchElem = document.getElementById("SearchKey");
    Samples.AspNet.HelloWorldService.HelloWorld(SrchElem.value,
      OnRequestComplete);
  }

  function OnRequestComplete(result)
  {
    var RsltElem = document.getElementById("Results");
    RsltElem.innerHTML = result;
  }

  </script>
   
  <script type="text/xml-script">
    <page xmlns:script="http://schemas.microsoft.com/xml-script/2005">
      <references>
          <add src="ScriptLibrary/AtlasUI.js" />
          <add src="ScriptLibrary/AtlasControls.js" />
      </references>
      <components>
          <textBox id="SearchKey">
              <behaviors>
                  <autoComplete
                    completionList="completionList"
                    serviceURL="AutoCompleteService.asmx"
                    serviceMethod="GetWordList"
                    minimumPrefixLength="2"
                    completionSetCount="15"
                    completionInterval="500" />
              </behaviors>
          </textBox>
      </components>
    </page>
  </script>
   
</asp:Content>

我们要注意:
Atlas界面元素是被定义在<components>子元素里面的;Behaviors被当做UI元素的子元素。Behavior联系id是SearchKey的textbox,对于autoComplete行为,他的属性意思如下:
1,completionList属性指定 一个显示自动完成数据的UI元素的id。
2,
serviceURL说的就是web service。
3,
serviceMethod就是我们在web service里面写的那个返回数据的方法
4,
minimumPrefixLength指定当在文本框里面输入多少字符的时候才开始调用那个web service里面的方法显示数据
5,
completionSetCount设置显示多少条数据
6,
completionInterval设置显示自动完成数据的延迟豪秒数啊
有三个属性是必须的:completionList
, serviceURL, 和 serviceMethod
好拉,现在我们运行下,效果就出来拉!!