一步一步学Silverlight 2系列(25):综合实例之Live Search

概述

Silverlight 2 Beta 1版本发布了,无论从Runtime还是Tools都给我们带来了很多的惊喜,如支持框架语言Visual Basic, Visual C#, IronRuby, Ironpython,对JSON、Web Service、WCF以及Sockets的支持等一系列新的特性。《一步一步学Silverlight 2系列》文章将从Silverlight 2基础知识、数据与通信、自定义控件、动画、图形图像等几个方面带您快速进入Silverlight 2开发。

本节将综合前面几篇介绍与浏览器交互部分内容,做一个综合示例——Live Search

准备知识

在本示例中,我们将通过调用Live Search API,在Silverlight中动态创建DOM结构,将搜索的结果展现出来。在使用Live Search API之前,需要先去Live Search Developer Center申请一个应用程序ID。

TerryLee_Silverlight2_0115

申请完成后应用程序ID大约在10分钟左右生效。关于Live Search API的有关详细信息,请大家参考这里

编写ASMX

直接调用API,返回的信息可能有很多,为了简单起见,我们对返回的结果做一些处理,编写一个SearchResultItem类:

public class SearchResultItem
{
    public string Title { get; set; }

    public string Url { get; set; }

    public string Description { get; set; }
}

添加对Live Search API的Service引用,地址为:http://soap.search.live.com/webservices.asmx?wsdl

TerryLee_Silverlight2_0118

在ASMX中对返回的结果进行一些处理,Silverlight程序最后将直接调用ASMX。在调用Live Search时需要指定应用程序ID以及本地化的信息等,查询的参数将在Silverlight程序中调用时传入。

[WebMethod]
public SearchResultItem[] DoSearch(string query)
{
    MSNSearchPortTypeClient s = new MSNSearchPortTypeClient();
    SearchRequest searchRequest = new SearchRequest();
    int arraySize = 1;
    SourceRequest[] sr = new SourceRequest[arraySize];

    sr[0] = new SourceRequest();
    sr[0].Source = SourceType.Web;

    searchRequest.Query = query;
    searchRequest.Requests = sr;

    searchRequest.AppID = "C0680205851CCC0E38946DB8FF74156C1C826A86";
    searchRequest.CultureInfo = "zh-CN";
    SearchResponse searchResponse;

    searchResponse = s.Search(searchRequest);

    List<SearchResultItem> lists = new List<SearchResultItem>();
    foreach (SourceResponse sourceResponse in searchResponse.Responses)
    {
        Result[] sourceResults = sourceResponse.Results;
        foreach (Result sourceResult in sourceResults)
        {
            SearchResultItem item = new SearchResultItem();
            if ((sourceResult.Title != null) && (sourceResult.Title != String.Empty))
                item.Title = sourceResult.Title;

            if ((sourceResult.Description != null) && (sourceResult.Description != String.Empty))
                item.Description = sourceResult.Description;

            if ((sourceResult.Url != null) && (sourceResult.Url != String.Empty))
                item.Url = sourceResult.Url;

            lists.Add(item);
        }
    }
    return lists.ToArray();
}

测试一下我们的服务是否正常:

TerryLee_Silverlight2_0116 

修改测试页

在测试ASPX中,修改Silverlight插件的样式控制,并添加一个div用来显示搜索的结果:

<div  style="height:100%;">
    <asp:Silverlight ID="Xaml1" runat="server" 
        Source="~/ClientBin/TerryLee.SilverlightGoogleSearch.xap"
        Version="2.0" Width="857" Height="140" />
    <div id="result"></div>
</div>

定义几个简单的样式:

<style type="text/css">
    #result
    {
        margin-left:20px;
    }
    .urlstyle
    {
        color:#59990E;
    }
    .itemstyle
    {
        border-bottom:dotted 1px #59990E;
        margin-bottom:20px;
    }
</style>

实现Silverlight程序

编写一个简单的Silverlight界面,使其看起来如图所示:

TerryLee_Silverlight2_0117

XAML声明如下:

<Grid x:Name="LayoutRoot" Background="White">
    <Grid.RowDefinitions>
        <RowDefinition Height="55"></RowDefinition>
        <RowDefinition Height="50"></RowDefinition>
        <RowDefinition Height="35"></RowDefinition>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"></ColumnDefinition>
    </Grid.ColumnDefinitions>
    
    <Image Source="LiveSearch.png" Grid.Column="0"></Image>
    <StackPanel Grid.Row="1" Orientation="Horizontal">
        <TextBox x:Name="txtQuery" Width="400" Height="35"
                 Margin="50 0 0 0" BorderBrush="#3F7801"></TextBox>
        <Button x:Name="btnSearch" Width="120" Height="35"
                Background="#62A21D" Margin="20 0 0 0"
                Content="Search" FontSize="16" Click="btnSearch_Click"></Button>
    </StackPanel>
    <TextBlock Grid.Row="2" Text="网页搜索结果" Foreground="#59990E"
               FontSize="16" Margin="20 0 0 0"></TextBlock>
</Grid>

在Silverlight项目中添加对于ASMX的引用,并编写“Search”按钮的实现,对于如何调用ASMX,可以参考一步一步学Silverlight 2系列(15):数据与通信之ASMX。动态创建DOM结构,并将结果显示出来:

private void btnSearch_Click(object sender, RoutedEventArgs e)
{
    LiveSearchWebServiceSoapClient client = new LiveSearchWebServiceSoapClient();

    client.DoSearchCompleted += new EventHandler<DoSearchCompletedEventArgs>(client_DoSearchCompleted);
    client.DoSearchAsync(this.txtQuery.Text);
}

void client_DoSearchCompleted(object sender, DoSearchCompletedEventArgs e)
{
    if (e.Error == null)
    {
        SearchResultItem[] results = e.Result as SearchResultItem[];

        HtmlElement result = HtmlPage.Document.GetElementById("result");

        foreach (SearchResultItem item in results)
        {
            HtmlElement itemElement = HtmlPage.Document.CreateElement("div");
            itemElement.CssClass = "itemstyle";

            HtmlElement titleElement = HtmlPage.Document.CreateElement("a");
            titleElement.SetAttribute("href",item.Url);
            titleElement.SetAttribute("innerText",item.Title);

            HtmlElement descriptElement = HtmlPage.Document.CreateElement("div");
            descriptElement.SetAttribute("innerText",item.Description);

            HtmlElement urlElement = HtmlPage.Document.CreateElement("span");
            urlElement.SetAttribute("innerText",item.Url);
            urlElement.CssClass = "urlstyle";

            itemElement.AppendChild(titleElement);
            itemElement.AppendChild(descriptElement);
            itemElement.AppendChild(urlElement);

            result.AppendChild(itemElement);
        }
    }
}

运行看一下效果,查询博客园:

TerryLee_Silverlight2_0119

结束语

本文综合了前面关于浏览器集成以及数据与通信部分的内容,开发了一个综合的示例——Live Search。你可以从这里下载本文示例代码。

作者:TerryLee
出处:http://terrylee.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
标签: Silverlight
posted @ 2008-03-15 17:10 TerryLee 阅读(11950) 评论(41) 编辑 收藏

 回复 引用 查看   
#1楼 2008-03-15 17:31 侯垒      
楼主的学习速度太快了.佩服.
能否提供点学习的方法之类的?让我们都学习一下.

 回复 引用 查看   
#2楼[楼主] 2008-03-15 17:45 TerryLee      
@侯垒
呵呵,没什么了,多看一些资料如SDK等和相关的文章,多做示例:)

 回复 引用 查看   
#3楼 2008-03-15 17:45 秋千      
楼主真厉害,写的速度比我看的都快
 回复 引用 查看   
#4楼[楼主] 2008-03-15 18:02 TerryLee      
@秋千
呵呵:)

 回复 引用   
#5楼 2008-03-15 19:20 AllanChan[未注册用户]
持续关注。。。
 回复 引用 查看   
#6楼 2008-03-15 21:01 真见      
你能不能把你电脑现在的这个桌面主题包共享一下呀,,我找不到啊。。。在虚拟机上用vista的系统装08成功了,想要你的这个系统的主题风格。。。希望贴出来,,万分感激。。。搞不好你一举粉丝又多了
 回复 引用 查看   
#7楼[楼主] 2008-03-15 22:27 TerryLee      
@AllanChan
谢谢:)

 回复 引用 查看   
#8楼[楼主] 2008-03-15 22:28 TerryLee      
@真见
这个还是不要了吧,如果有时间你可以发邮件给我:)

 回复 引用 查看   
#9楼 2008-03-15 23:57 仁面寿星      
您好,接您的人气询问一下大家。
我用VS2008中文版只安装了Silverlight 2 beta1但是添加项目的时候无法找到SL的项目,请问是什么问题?还需要装什么吗?

 回复 引用 查看   
#10楼[楼主] 2008-03-16 00:19 TerryLee      
@仁面寿星
参考这篇文章
http://www.cnblogs.com/Terrylee/archive/2008/03/06/Silverlight-Beta1-and-ASPNET-MVC-Preview2-and-IE8-Beta1.html
看你下载的是哪个组件?如果安装silverlight_chainer.exe(54.5M),所有的组件就都有了

 回复 引用   
#11楼 2008-03-17 10:40 力大无比[未注册用户]
勾起了我的食欲
 回复 引用 查看   
#12楼[楼主] 2008-03-17 19:14 TerryLee      
@力大无比
可以学习一下啊:)

 回复 引用 查看   
#13楼 2008-05-23 16:26 蓝色飞翔      
今天剛剛開始正式學習 Silverlight .
找到了這個好地方。 呵呵。謝謝了!

 回复 引用   
#14楼 2008-07-24 17:06 StrongBird[未注册用户]
李大哥,请问一下:
searchRequest.AppID = "C0680205851CCC0E38946DB8FF74156C1C826A86"
中的AppID是什么意思,怎么得到的?

 回复 引用   
#15楼 2008-07-24 17:09 StrongBird[未注册用户]
哦,我明白了,是注册Live Search帐号的时候得到的。呵呵看起来太Ugly了……
 回复 引用 查看   
#16楼[楼主] 2008-07-25 09:50 TerryLee      
@StrongBird
是的,需要申请一个应用程序ID

 回复 引用   
#17楼 2008-07-27 18:48 baohan[未注册用户]
我在调用的Live search api创建了一个webservice,在本机运行没问题,发布到美国的服务器却有socket异常,李哥能猜测下原因吗,不知道是不是appID的原因
 回复 引用 查看   
#18楼[楼主] 2008-07-27 21:37 TerryLee      
@baohan
这个不太好猜测是什么原因,呵呵

 回复 引用   
#19楼 2008-09-12 16:49 lujianno11[未注册用户]
为什么我按照你的方法全部写 e.Result as SearchResultItem[];的时候,提示说错误 无法通过引用转换、装箱转换、取消装箱转换、包装转换或 Null 类型转换将类型“System.Collections.ObjectModel.ObservableCollection<SilverlightApplication11.LiveSearchWebService.SearchResultItem>”转换为“SilverlightApplication11.LiveSearchWebService.SearchResultItem[]”,这是什么问题,谢谢
 回复 引用 查看   
#20楼[楼主] 2008-09-17 01:05 TerryLee      
@lujianno11
这跟Silverlight版本有关系,在Beta 2下添加Web Service引用时会转换为ObservableCollection集合

 回复 引用   
#21楼 2008-09-25 15:11 tienhy[未注册用户]
--引用--------------------------------------------------
TerryLee: @lujianno11
这跟Silverlight版本有关系,在Beta 2下添加Web Service引用时会转换为ObservableCollection集合
--------------------------------------------------------
如何解决。

 回复 引用 查看   
#22楼 2008-09-26 11:10 rockey      
LZ给出的http://soap.search.live.com/webservices.asmx?wsdl 有问题?
我自己找了下 现在换成 http://soap.search.msn.com/webservices.asmx?wsdl 不知道是不是这样的?

还有就是测试 liveSearchweb 服务的时候出错
System.ServiceModel.ProtocolException: 响应消息的内容类型 text/html;charset=gb2312 与绑定(text/xml; charset=utf-8)的内容类型不匹配。如果使用自定义编码器,请确保正确实现 IsContentTypeSupported 方法。响应的前 616 个字节为:“<!--
���ļ�������lighttpd��nginxת������������
-->
代码全部复制你的(实在是找不到原因)
帮看看是怎么回事吧

 回复 引用 查看   
#23楼[楼主] 2008-10-08 11:41 TerryLee      
@rockey
http://soap.search.live.com/webservices.asmx?wsdl这个地址没问题的,放在浏览器中打开一下看看。

 回复 引用 查看   
#24楼[楼主] 2008-10-08 11:42 TerryLee      
@tienhy
在.NET中类型转换不会吗?

 回复 引用 查看   
#25楼 2008-11-20 14:49 laurel's blog      
这块程序的代码没提供下载吗?
我这怎么一直有错,能提供份代码下载?
或者发我一份,谢谢!
tygx99#yahoo.com.cn

 回复 引用 查看   
#26楼[楼主] 2008-11-20 23:50 TerryLee      
@laurel's blog
现在提供代码也没用了,因为本文示例是Beta 1的

 回复 引用 查看   
#27楼 2008-12-30 10:38 根总      
System.Collections.ObjectModel.ObservableCollection<SearchResultItem> results = e.Result;
//SearchResultItem[] results = e.Result as SearchResultItem[];
这样就解决了转换问题

 回复 引用 查看   
#28楼[楼主] 2009-01-04 11:25 TerryLee      
@根总
:)

 回复 引用   
#29楼 2009-01-06 14:41 lalala[未注册用户]
terrylee 我佩服死你了。。WindowsLive你也懂。。膜拜~~
 回复 引用 查看   
#30楼[楼主] 2009-01-06 18:35 TerryLee      
@lalala
Windows Live其实使用的时候,查一下它的相关SDK就可以了,呵呵。

 回复 引用   
#31楼 2009-01-12 09:33 kurokawa[未注册用户]
博主你好!我在使用MSNLiveSearch的时候碰到有些API提供的方法跟你教程里不一致的问题。主要就是MSNSearchPortTypeClient.Search()这个方法,现在这个WebService可能是版本更新了的缘故,好像已经取消了Search()这个方法,取而代之的是SearchAsync()这个方法,但是新的方法不返回任何值,我就不知道怎样获取SearchResponse的实例了,请博主指点一下!
 回复 引用 查看   
#32楼[楼主] 2009-01-12 10:29 TerryLee      
@kurokawa
SearchAsync()只是Search()的异步方法而已。

 回复 引用   
#33楼 2009-01-12 10:46 kurokawa[未注册用户]
是的,但是问题是现在没有了Search()方法,SearchAsync()的返回值也改为void了,所以编程逻辑要作些修改,刚刚上网看过一下,貌似取消了显式定义SearchResponse的实例来获取搜索结果。
 回复 引用 查看   
#34楼 2009-01-14 21:24 ColdDog      
刚看到这里,后面的文章还来不及看,等不及了,先咨询下楼主,请问SL能像flash那样,调用socket进行通信吗?可能我表述不正确,就是那种类似几个客户端之间的通信,可否做到实时通信?就类似这样,比如做一个网络版斗地主。
谢谢!

 回复 引用   
#35楼 2009-05-26 23:51 杨子国
前辈,你好,我想请教个问题,在silverlignt应用开发完后,会有相应的网站和silverlignt应用程序,怎样把这两个一起打包并进行发布呢?
我将非常感谢您的帮助!

 回复 引用 查看   
#36楼 2010-08-14 12:14 fisea      
请TerryLee解决这个问题。谢谢!
我是按照你的一步步来做的,运行时候出现如下问题:
System.ServiceModel.FaultException: Client Error

Server stack trace:
at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ProxyRpc& rpc)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at LiveSearch.Web.LiveSearchService.MSNSearchPortType.Search(SearchRequest Request)
at LiveSearch.Web.LiveSearchService.MSNSearchPortTypeClient.Search(SearchRequest Request) in E:\silverlight\LiveSearch\LiveSearch.Web\Service References\LiveSearchService\Reference.cs:line 1852
at LiveSearch.Web.SearchService.DoSearch(String query) in E:\silverlight\LiveSearch\LiveSearch.Web\SearchService.asmx.cs:line 39