用VS2005创建一个Atlas Web应用程序(3) 作者: dengsu888666 发表日期: 2006-09-19 10:55 文章属性: 原创 复制链接 |
本文要介绍的是微软新开发技术中的自动完成特性,在本例中你可以学到怎么设置自动完成功能、在自动完成功能中如何通过调用Web服务获取服务端的数据,如何把本功能和页面上的TextBox控件建立联系以便在用户输入文本时完成自动弹出下拉框功能。 首先,按照第一篇文章介绍的步骤创建一个Atlas的Web应用程序。在这里我重点介绍为自动完成功能提供数据的Web服务和客户端的两种实现方式。创建一个Web服务,它用来从一个文本文件里读取数据并返回给客户端脚本的回调函数。客户端脚本用这些数据为TextBox显示自动弹出下拉框。Atlas客户端角脚本库对服务端平台和服务没什么特别要求,它适用于任何服务平台和Web服务。 1.我们先添加一个文本文件Words.txt放在App_Data目录里,例如,words.txt里放入的内容如下: access control list (ACL) ADO.NET aggregate event alpha channel anchoring antialiasing application base application domain (AppDomain) application manifest application state ASP.NET ASP.NET application services database ASP.NET mobile controls ASP.NET mobile Web Forms ASP.NET page ASP.NET server control ASP.NET Web application assembly assembly cache assembly manifest assembly metadata assertion (Assert) association class ASSOCIATORS OF asynchronous method attribute authentication authorization autopostback bounds boxing C# card catalog CCW chevron chrome cHTML CIM CIM Object Manager CIM schema class client area client coordinates clip closed generic type CLR CLS CLS-compliant code access security code-behind class code-behind file code-behind page COM callable wrapper (CCW) COM interop Common Information Model (CIM) common language runtime common language runtime host Common Language Specification (CLS) common object file format (COFF) common type system (CTS) comparison evaluator composite control configuration file connection connection point constraint constructed generic type constructed type consumer container container control content page context context property contract control state cross-page posting CTS custom attribute (Attribute) custom control 2.添加一个Web服务,命名为AutoCompleteService.asmx,不要选择“把代码放在单独的文件中”选择项。在代码里添加一个GetWordList方法,它根据用户输入的字符串前缀和字符串个数来返回相匹配的字符串列表完成自动完成功能。完整的Web服务代码如下: C#代码: <%@ 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) { string[] temp = File.ReadAllLines(Server.MapPath("~/App_Data/words.txt")); Array.Sort(temp, new CaseInsensitiveComparer()); autoCompleteWordList = temp; } 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; } } } VB代码 <%@ WebService Language="VB" Class="Samples.AspNet.AutoCompleteService" %> Imports System Imports System.IO Imports System.Web Imports System.Collections Imports System.Collections.Generic Imports System.Threading Imports System.Web.Services Imports System.Web.Services.Protocols Imports System.Xml.Serialization Namespace Samples.AspNet <WebService(Namespace:="http://tempuri.org/")> _ <WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _ Public Class AutoCompleteService Inherits System.Web.Services.WebService Private Shared autoCompleteWordList As String() <WebMethod()> _ Public Function GetWordList(ByVal prefixText As String, _ ByVal count As Integer) As String() If autoCompleteWordList Is Nothing Then Dim temp As String() = File.ReadAllLines(Server.MapPath("~/App_Data/words.txt")) Array.Sort(temp, New CaseInsensitiveComparer()) autoCompleteWordList = temp End If Dim index As Integer = Array.BinarySearch(autoCompleteWordList, _ prefixText, New CaseInsensitiveComparer()) If index < 0 Then index = Not index End If Dim matchingCount As Integer For matchingCount = 0 To count - 1 If Not (matchingCount + index) < autoCompleteWordList.Length Then Exit For End If If Not autoCompleteWordList((index _ + matchingCount)).StartsWith(prefixText, _ StringComparison.CurrentCultureIgnoreCase) Then Exit For End If Next matchingCount Dim returnValue(matchingCount - 1) As String If matchingCount > 0 Then Array.Copy(autoCompleteWordList, index, returnValue, 0, _ matchingCount) End If Return returnValue End Function End Class End Namespace 可以在浏览器中直接测试这个Web服务,在浏览器中运行AutoCompleteService.asmx(在解决方案资源管理器中选中AutoCompleteService.asmx点击鼠标右键选择菜单“在浏览器中查看”),在网页中选择GetWordList会出现一个测试页面,在文本框中输入以下内容:prefixText输入com、count输入5, 点击Invoke按钮。你可以浏览到从words.txt文本文件中查找到的结果。如下图: 图1 ![]() 图2 ![]() 3.和第一篇文章介绍的步骤一样,添加一个带HelloWorld方法的Web服务,命名为HelloWorldService.asmx。它实现返回查询时间和查询结果,完整的代码如下: C#代码: <%@ WebService Language="C#" Class="Samples.AspNet.HelloWorldService" %> using System; using System.Web; using System.Web.Services; using System.Web.Services.Protocols; using System.IO; using System.Collections; using System.Collections.Generic; namespace Samples.AspNet { [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] public class HelloWorldService : System.Web.Services.WebService { private static string[] autoCompleteWordList = null; [WebMethod] public string HelloWorld(String query) { string[] resultArray = GetWordList(query, 5); string resultStr = ""; if (resultArray.Length > 0) { resultStr =resultStr+resultArray[0]; for (int j = 1; j < resultArray.Length; j++) resultStr = resultStr +";"+ resultArray[j]; } string inputString = Server.HtmlEncode(query); resultStr = Server.HtmlEncode(resultStr); if(!String.IsNullOrEmpty(inputString)) { return String.Format("Hello, you queried for {0}. The " + "current time is {1},result is {2}", inputString, DateTime.Now, resultStr); } else { return "The query string was null or empty"; } } private String[] GetWordList(string prefixText, int count) { if (autoCompleteWordList == null) { string[] temp = File.ReadAllLines(Server.MapPath("~/App_Data/words.txt")); Array.Sort(temp, new CaseInsensitiveComparer()); autoCompleteWordList = temp; } 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; } } } VB代码略 4.在这一步我们要用Atlas客户端脚本库产生一个具有自动完成功能的TextBox。我们先添加一个和第一篇文章一样的搜索Web页面(步骤见第一篇文章),命名为AutoComplete.aspx,在添加时不要选择“把代码放在单独的文件中”选择项。完整的代码如下: <%@ Page Language="C#" Title="Atlas AutoComplete Walkthrough" %> <!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"> <atlas:ScriptManager runat="server" ID="scriptManager"> <services> <atlas:servicereference path="HelloWorldService.asmx" type="text/javascript" /> </services> </atlas:ScriptManager> <style type="text/css"> body { font: 11pt Trebuchet MS; font-color: #000000; padding-top: 72px; text-align: center } .text { font: 8pt Trebuchet MS } </style> </head> <body> <form action="" runat="server"> <div> Search for <input id="SearchKey" type="text" /> <input id="SearchButton" type="button" value="Search" οnclick="DoSearch()"/> </div> </form> <div id="completionList"></div> <hr style="width: 300px"/> <div> <span id="Results"></span> </div> <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"> <components> <textBox id="SearchKey"> <behaviors> <autoComplete completionList="completionList" serviceURL="AutoCompleteService.asmx" serviceMethod="GetWordList" minimumPrefixLength="2" completionSetCount="15" completionInterval="500" /> </behaviors> </textBox> </components> </page> </script> </body> </html> 这个页面调用了两个Web服务,第一个Web服务调用是在第一个<script>元素里,通过客户端脚本的形式进行调用HelloWorldService.asmx的,第二个Web服务调用是在第二个<script>元素里,它是通过客户端脚本声明性语法调用AutoCompleteService.asmx的,它是对TextBox完成自动完成功能的,必须要声明<textbox>元素,并且添加<autoComplete>元素通过属性声明自动完成功能的有关细节。 这里要注意,在Web.config的配置文件里的<system.web>的元素里要有下面配置: <pages> <controls> <add namespace="Microsoft.Web.UI" assembly="Microsoft.Web.Atlas" tagPrefix="atlas"/> <add namespace="Microsoft.Web.UI.Controls" assembly="Microsoft.Web.Atlas" tagPrefix="atlas"/> </controls> </pages> 否则编译时会提示未知的服务器标记atlas:ScriptManager。 现在这个Atlas的Web程序就大功告成了,你可以测试效果了,运行AutoComplete.aspx,在搜索文本框里输入超过2个字符后,可以看到文本框下面会自动显示匹配字符串的列表。点击Search按钮,会返回查询时间和最多5个的查询结果。如下图: 图3 ![]() 从上面的例子中可以看到,你在创建一个Atlas客户端程序时,可以使用客户端脚本调用Web服务或使用客户端脚本声明方式同UI控件元素进行关联通过行为来调用Web服务的两种的任何一种方式来完成。在这里你只需要对客户端脚本声明做一个了解,理解它的原理就可以了,下一篇文章将专门介绍客户端脚本声明的实现技术。 演示代码下载3 AtlasTest3.rar |