说明:本系列基本上是《WPF揭秘》的读书笔记。在结构安排与文章内容上参照《WPF揭秘》的编排,对内容进行了总结并加入一些个人理解。

这一部分我们重点讨论下Silverlight的网络与通讯功能。2.0版起,Silverlight支持多种模式的网络访问,从最原始的Silverlight控件支持的JavaScript方法,到Silverlight Framework内置的通过C#操作的各种类,几乎可以实现任意你想实现的功能。下面我们逐一讨论这些方法:

  1. 通过Silverlight控件的JavaScript支持

    这种方式的最终目的无非是把通过JavaScript获取的网络数据赋给Silverlight中的元素,代码大致如下所示:

     var valFromNet;
    var SL = document.getElementById("silverlightPlugIn");
    SL.content.findName("txt").Text = valFromNet;
    而JavaScript获取数据的方法又分如下两种:
  1. 编写使用xmlHttpRequest组件的JavaScript以Ajax方式异步获取数据

    我们通过如下代码段看一下这种方式的实现:

     function getAsyncResult() {
    xmlHttp = new XMLHttpRequest();
    xmlHttp.open("GET", "http://localhost:36360/ServerTime.ashx", true);
    xmlHttp.onreadystatechange = handleAJAXCallback;
    xmlHttp.send(null);
    } function handleAJAXCallback() {
    if ((xmlHttp.readyState == 4) && (xmlHttp.status == 200)) {
    var SL = document.getElementById("silverlightPlugIn");
    SL.content.findName("txt").Text = xmlHttp.responseText;
    }
    }

    可见,在回调函数中将异步获取的结果设置给Silverlight的元素。这个例子中我们访问的是一个ASP.NET编写的HttpHandler,可以将其换成其它任何可得到数据的Url。值得一提的在回调函数中队XmlHttpRequest的状态进行了检测,4即表示请求完成。

  1. 在Silverlight项目中添加ASP.NET Web服务的引用,并访问

    在Silverlight中添加了对包含标记了[System.Web.Script.Services.ScriptService]属性的服务(方法也需要被标记为[WebMethod])的引用后,并页面中使用ScriptManager控件引用服务时,会自动生成JavaScript代理,这正是我们需要的东西,我们通过它来访问服务。完成上面的操作后我们就可以使用如下的JavaScript代码访问Web Service来获取我们想要的数据。

    注意在生成的JavaScript代理中我们使用WebServiceName.WebMethod这样的对象名来访问服务。

     function onLoad()
    {
    Service.getTime(onSuccess, onFailed,"");
    } function onSuccess(result)
    {
    var sl = document.getElementById("silverlightPlugIn");
    sl.content.findName("txtShort").Text = result.strShortTime;
    sl.content.findName("txtLong").Text = result.strLongTime;
    } function onFailed(result)
    {
    alert(result);
    }

    此处得到的result这个对象 ,已经被序列化为JSON格式。

  1. Silverlight Framework中的WebClinet与WebRequest方法

    首先我们来了解下WebClient的功能,在使用.NET进行Silverlight编程时,WebClient提供了最简单易用的网络访问功能,这个类的两个方法DownloadStringAsync与OpenReadAsync分别用来获取字符串及获取其它类型的数据,这些方法也是异步方法对应的回调函数分别为DownloadStringCompleted和OpenReadCompleted。下面的代码使用DownloadStringAsync演示了WebClient的使用:

     public Page()
    {
    InitializeComponent();
    WebClient cl = new WebClient();
    Uri uri = new Uri("http://localhost:36360/Web/Time.ashx"); cl.DownloadStringCompleted += new DownloadStringCompletedEventHandler(cl_DownloadStringCompleted);
    cl.DownloadStringAsync(uri);
    } void cl_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
    {
    txtTime.Text = e.Result;
    }

    注意,使用WebClient需要添加对System.Net命名空间的引用。WebClient中其它常用属性还包括IsBusy,当数据在传输过程中此值返回true。WebClient中CancelAync方法用来取消正在进行的异步传输,并且此时DownloadStringCompleted/OpenReadCompleted事件参数的Cancelled属性会被置为true。
    接下来要介绍的是WebRequest类,这个类用来实现标准HTTP请求,主要包括一些通过POST来访问的地址。这个类的使用与.NET Framework中的HttpWebRequest很相似,下面给出一段核心代码作为示例:

     private void b_Click(object sender, RoutedEventArgs e)
    {
    Uri uri = new Uri("http://localhost:22602/WebRequestTest_Web/SubmitForm.ashx");
    WebRequest rq = WebRequest.Create(uri);
    rq.Method = "POST";
    rq.ContentType = "application/x-www-form-urlencoded";
    rq.BeginGetRequestStream(new AsyncCallback(RequestReady), rq);
    rq.BeginGetResponse(new AsyncCallback(ResponseReady), rq);
    }
    void RequestReady(IAsyncResult aR)
    {
    WebRequest rq = aR.AsyncState as WebRequest;
    Stream rqStream = rq.EndGetRequestStream(aR);
    StreamWriter w = new StreamWriter(rqStream);
    w.Write("t1=" + t1.Text + "&");
    w.Write("t2=" + t2.Text + "&");
    w.Write("t3=" + t3.Text );
    w.Flush();
    }

    上面代码中在获取请求数据与获取响应数据时都是发起的异步请求,在获取响应数据完成时需要下面的回调函数处理完成事件:

     void ResponseReady(IAsyncResult aR)
    {
    WebRequest rq = aR.AsyncState as WebRequest;
    using(WebResponse rs = rq.EndGetResponse(aR))
    using (Stream rpStream = rs.GetResponseStream())
    {
    StreamReader rdr = new StreamReader(rpStream);
    string postStatus = rdr.ReadToEnd();
    }
    }
  1. 在Silverlight中使用WCF

    Silverlight Framework中System.ServiceModel中的类提供了Silverlight对WCF的支持。下面的小例子给出了演示,我们通过在Visual Studio中添加WCF的引用来生成一个代理,这大大减少了编码的复杂度。我们逐段代码分析这个例子:
    首先是一个DataContract,这是服务器端与客户端传输数据类型的一个契约:

     [DataContract]
    public class Person
    {
    public Person(string strName, string strAge)
    {
    Name = strName;
    Age = strAge;
    }
    [DataMember]
    public string Name { get; set; }
    [DataMember]
    public string Age { get; set; }
    }

    然后是服务代码,这其中包括服务契约与服务实现:

     [ServiceContract]
    public interface IPersonService
    {
    [OperationContract]
    Person[] getPeople();
    } public class PersonService : IPersonService
    {
    public Person[] getPeople()
    {
    Person[] people =
    {
    new Person("Derek Snyder",""),
    new Person("Yoshi Latimer",""),
    new Person("Mark Steel","")
    };
    return people;
    }
    }

    对于这个简单的示例我们使用basicHttpBinding,服务的config中ServiceModel这部分参考如下代码:

     <system.serviceModel>
    <behaviors>
    <serviceBehaviors>
    <behavior name="PersonServiceBehavior">
    <serviceMetadata httpGetEnabled="true"/>
    <serviceDebug includeExceptionDetailInFaults="false"/>
    </behavior>
    </serviceBehaviors>
    </behaviors>
    <services>
    <service behaviorConfiguration="PersonServiceBehavior" name="PersonService">
    <endpoint address="" binding="basicHttpBinding" contract="IPersonService">
    <identity>
    <dns value="localhost"/>
    </identity>
    </endpoint>
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
    </service>
    </services>
    </system.serviceModel>

    以上就是服务部分重要的代码,在添加了WCF服务引用后我们就可以使用如下的代码在WCF中访问服务:

     public Page()
    {
    InitializeComponent();
    Binding binding = new BasicHttpBinding();
    EndpointAddress endPoint = new EndpointAddress("http://localhost:36360/WCFService/PersonService.svc");
    PSProxy.PersonServiceClient client = new PSProxy.PersonServiceClient(binding, endPoint);
    client.getPeopleCompleted += new EventHandler<PersonService.PSProxy.getPeopleCompletedEventArgs>(client_getPeopleCompleted);
    client.getPeopleAsync();
    }

    回调函数中我们把得到的对象绑定到ItemsControl的数据模板中:
    ItemControl的XAML:

     <ItemsControl x:Name="_item">
    <ItemsControl.ItemTemplate>
    <DataTemplate>
    <StackPanel Orientation="Vertical">
    <StackPanel Orientation="Horizontal">
    <TextBlock FontWeight="Bold" Text="{Binding Name}" />
    <TextBlock Text=" : "></TextBlock>
    <TextBlock FontWeight="Bold" Text="{Binding Age}" />
    </StackPanel>
    </StackPanel>
    </DataTemplate>
    </ItemsControl.ItemTemplate>
    </ItemsControl>

    回调函数:

     void client_getPeopleCompleted(object sender, PersonService.PSProxy.getPeopleCompletedEventArgs e)
    {
    _item.ItemsSource = e.Result;
    }

    客户端的配置在添加引用时自动生成不再赘述。

以上这些就是Silverlight中访问网络的主要方式。

本文完

WPF,Silverlight与XAML读书笔记第四十八 - Silverlight网络与通讯的更多相关文章

  1. WPF,Silverlight与XAML读书笔记第四十五 - 外观效果之模板

    说明:本系列基本上是<WPF揭秘>的读书笔记.在结构安排与文章内容上参照<WPF揭秘>的编排,对内容进行了总结并加入一些个人理解. 模板允许用任何东西完全替换一个元素的可视树, ...

  2. WPF,Silverlight与XAML读书笔记第四十四 - 外观效果之样式

    说明:本系列基本上是<WPF揭秘>的读书笔记.在结构安排与文章内容上参照<WPF揭秘>的编排,对内容进行了总结并加入一些个人理解. 如果你有Web编程的经验,你会知道使用Sty ...

  3. WPF,Silverlight与XAML读书笔记第四十六 - 外观效果之三皮肤与主题

    说明:本系列基本上是<WPF揭秘>的读书笔记.在结构安排与文章内容上参照<WPF揭秘>的编排,对内容进行了总结并加入一些个人理解. 皮肤 皮肤是应用程序中样式与模板的集合,可以 ...

  4. WPF,Silverlight与XAML读书笔记第三十九 - 可视化效果之3D图形

    原文:WPF,Silverlight与XAML读书笔记第三十九 - 可视化效果之3D图形 说明:本系列基本上是<WPF揭秘>的读书笔记.在结构安排与文章内容上参照<WPF揭秘> ...

  5. WPF,Silverlight与XAML读书笔记第四十七 - Silverlight与浏览器

    说明:本系列基本上是<WPF揭秘>的读书笔记.在结构安排与文章内容上参照<WPF揭秘>的编排,对内容进行了总结并加入一些个人理解. 这部分内容主要介绍Silverlight与浏 ...

  6. WPF,Silverlight与XAML读书笔记第四十三 - 多媒体支持之文本与文档

    说明:本系列基本上是<WPF揭秘>的读书笔记.在结构安排与文章内容上参照<WPF揭秘>的编排,对内容进行了总结并加入一些个人理解. Glyphs对象(WPF,Silverlig ...

  7. WPF,Silverlight与XAML读书笔记(3) - 标记扩展

    hystar的.Net世界 博客园 首页 新闻 新随笔 联系 管理 订阅 随笔- 103  文章- 0  评论- 107  WPF,Silverlight与XAML读书笔记(3) - 标记扩展   说 ...

  8. Java开发笔记(四十八)类的简单继承

    前面介绍了类的基本用法,主要是如何封装一个类的各项要素,包括成员属性.成员方法.构造方法等,想必大家对类的简单运用早已驾轻就熟.所谓“物以类聚,人以群分”,之所以某些事物会聚在一起,乃是因为它们拥有类 ...

  9. Python学习笔记(四十八)POP3收取邮件

    收取邮件就是编写一个MUA作为客户端,从MDA把邮件获取到用户的电脑或者手机上.收取邮件最常用的协议是POP协议,目前版本号是3,俗称POP3. Python内置一个poplib模块,实现了POP3协 ...

随机推荐

  1. 异步I/O操作

    今天在看boost库的时候注意到异步I/O操作时,缓冲区有效性问题. 如何实现异步操作:以异步读操作为例async_read(buffer, handler): void handler() {} v ...

  2. XE3随笔20:几个和当前路径相关的新函数

    偶然从 SysUtils 里发现了几个路径相关的函数, 以前没见过, 可能是 Delphi XE3 新增的: GetLocaleDirectory(); GetLocaleFile(); Locale ...

  3. Shell文本处理 - 分割合并与过滤

    sort分类操作 示例文件 Boys in Company C:HK:192:2192 Alien:HK:119:1982 The Hill:KL:63:2972 Aliens:HK:532:4892 ...

  4. 图解VMware内存机制

    在写<VMware内存机制初探>之后,原本是计划写一篇<VMware内存机制再探>的,讲一讲VMware内存机制中的另外几个重要内容,比如透明内存共享(TPS, Transpa ...

  5. css鼠标手型cursor中hand与pointer

    css鼠标手型cursor中hand与pointer Example:CSS鼠标手型效果 <a href="#" style="cursor:hand"& ...

  6. mysql 行变列(多行变成一行/多行合并成一行/多行合并成多列/合并行)

    数据库结构如图: 而我想让同一个人的不同成绩变成此人在这一行不同列上显示出来,此时分为2中展现: 第一种展现如图----[多行变一列](合并后的数据在同一列上): sql如下: select name ...

  7. php内核探索 [转]

    PHP内核探索:从SAPI接口开始 PHP内核探索:一次请求的开始与结束 PHP内核探索:一次请求生命周期 PHP内核探索:单进程SAPI生命周期 PHP内核探索:多进程/线程的SAPI生命周期 PH ...

  8. ASP数组全集,多维数组和一维数组[转]

    ASP数组是比较好用的装载大量数据的容器.1 定义数组 有两种方式:DIM和REDIM. DIM定义的是固定个数.数据类型的数组:而REDIM则不同,它可以定义不同类型的数据,也可以定义个数并非固定的 ...

  9. js阻止提交表单(post)

    在注册页面,我们经常要用到页面验证,验证到不符合要求的数据就阻止提交到服务器,如下 <script type="text/javascript"> function C ...

  10. jquery 判断checkbox是否选中几个版本的区别

    $('#checkbox1').prop('checked') - in jQuery 1.6+, usually the way to go $('#checkbox1').is(':checked ...