稳扎稳打Silverlight(56) - 4.0通信之与 WCF Data Services 进行通信

http://tech.cncms.com/web/aspnet/3266.html


介绍

Silverlight 4.0 对 WCF Data Services 的支持:

* DataServiceCollection<T> - 继承自 ObservableCollection<T>,用于将 WCF Data Services 提供的数据绑定到 Silverlight 控件上,当数据发生变化时可提供通知

在线DEMO

http://www.cnblogs.com/webabcd/archive/2010/08/09/1795417.html

示例

演示 Silverlight 4.0 与 WCF Data Services 之间的通信

1、服务端

MyWCFDataService.svc.cs

代码

/*
 * WCF Data Services - 用于提供基于 OData 协议的数据服务
 * OData 协议 - 开放数据协议(Open Data Protocol),其基于 REST-ful 协议,参考:http://www.odata.org/
 */

using System;
using System.Collections.Generic;
using System.Data.Services;
using System.Data.Services.Common;
using System.Linq;
using System.ServiceModel.Web;
using System.Web;

namespace Silverlight40.Web.Service
{
    public class MyWCFDataService : DataService<Model.NorthwindEntities>
    {
        public static void InitializeService(DataServiceConfiguration config)
        {
            config.SetEntitySetAccessRule("*", EntitySetRights.All);

            // 指定对 Products, Categories, Orders 启用服务端分页,页大小为 3
            config.SetEntitySetPageSize("Products", 3);
            config.SetEntitySetPageSize("Categories", 3);
            config.SetEntitySetPageSize("Orders", 3);

            config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
        }
    }
}

2、客户端

Demo.xaml

代码

<navigation:Page x:Class="Silverlight40.WCFDataServices.Demo"
           xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
           xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
           xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
           xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
           xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
           xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
           Title="Demo Page">
    <Grid x:Name="LayoutRoot">
        <StackPanel Orientation="Vertical" HorizontalAlignment="Left">

            <!--
                    用于演示通过 WCF Data Services 实现数据的增删改查
                -->
            <StackPanel Orientation="Horizontal">
                <Button Name="btnGetData" Content="获取数据" Margin="5" Click="btnGetData_Click" />
            </StackPanel>

            <TextBlock Text="产品类别列表:" Margin="5" />
            <sdk:DataGrid Name="gridCategory" Margin="5" Height="200" Width="400" AutoGenerateColumns="False" ItemsSource="{Binding}"
                       SelectionChanged="gridCategory_SelectionChanged">
                <sdk:DataGrid.Columns>
                    <sdk:DataGridTextColumn Header="类别ID" Binding="{Binding CategoryID}" IsReadOnly="True" />
                    <sdk:DataGridTextColumn Header="类别名称" Binding="{Binding CategoryName}" />
                </sdk:DataGrid.Columns>
            </sdk:DataGrid>

            <TextBlock Text="产品列表:" Margin="5" />
            <sdk:DataGrid Name="gridProduct" Margin="5" Height="200" Width="400" AutoGenerateColumns="False" ItemsSource="{Binding}" >
                <sdk:DataGrid.Columns>
                    <sdk:DataGridTextColumn Header="产品ID" Binding="{Binding ProductID}" IsReadOnly="True" />
                    <sdk:DataGridTextColumn Header="产品名称" Binding="{Binding ProductName}" />
                    <sdk:DataGridTextColumn Header="单价" Binding="{Binding UnitPrice}" IsReadOnly="True" />
                </sdk:DataGrid.Columns>
            </sdk:DataGrid>

            <Button Name="btnSave" Content="保存" Margin="5" Width="400" Click="btnSave_Click" />

 

            <!--
                    用于演示 WCF Data Services 的服务端分页
                -->
            <TextBlock Text="订单列表:" Margin="5,20,5,5" />
            <sdk:DataGrid Name="gridOrder" Margin="5" Height="200" Width="400" IsReadOnly="True" AutoGenerateColumns="False" ItemsSource="{Binding}" >
                <sdk:DataGrid.Columns>
                    <sdk:DataGridTextColumn Header="订单ID" Binding="{Binding OrderID}" />
                    <sdk:DataGridTextColumn Header="客户ID" Binding="{Binding CustomerID}" />
                </sdk:DataGrid.Columns>
            </sdk:DataGrid>
            <TextBlock Name="txtCurrentPageIndex" />
            <Button Name="btnPrev" Content="上一页" Margin="5" Width="400" />
            <Button Name="btnNext" Content="下一页" Margin="5" Width="400" />

        </StackPanel>
    </Grid>
</navigation:Page>

Demo.xaml.cs

代码

/*
 * 演示 Silverlight 4.0 与 WCF Data Services 之间的通信
 *
 * DataServiceCollection<T> - 继承自 ObservableCollection<T>。用于将 WCF Data Services 提供的数据绑定到 Silverlight 控件上,当数据发生变化时可提供通知
 *     LoadAsync(IQueryable<T>) - 从数据服务上异步加载 IQueryable<T> 数据到 DataServiceCollection<T> 中(在 LoadCompleted 触发之前不能再调用此方法)
 *     LoadAsync() - 当 DataServiceCollection<T> 表示为某实体的导航属性时,从数据服务上异步加载该数据(在 LoadCompleted 触发之前不能再调用此方法)
 *     LoadCompleted - 异步加载完成后所触发的事件
 *         LoadCompletedEventArgs - LoadCompleted 事件的事件参数
 *         LoadCompletedEventArgs.QueryOperationResponse - 获取数据服务对改查询操作的响应
 *             QueryOperationResponse.Error - 引发的异常
 *             QueryOperationResponse.Headers -  HTTP 的响应头
 *             QueryOperationResponse.Query - 对应的 DataServiceQuery(DataServiceQuery.RequestUri - 请求数据服务的 URI) 对象
 *             QueryOperationResponse.StatusCode - HTTP 的响应代码
 *     Continuation - 返回一个 DataServiceQueryContinuation<T> 对象,该对象封装了当前查询结果的下一页的 URI
 *         DataServiceQueryContinuation<T>.NextLinkUri - 当前查询结果的下一页的 URI
 *     LoadNextPartialSetAsync() - 加载下一页数据到 DataServiceCollection<T> 中
 *
 * Silverlight 通过 ObservableCollection<T> 与 ADO.NET Data Services 1.0 进行通信详见 http://www.cnblogs.com/webabcd/archive/2009/03/12/1409281.html
 * WCF Data Services(ADO.NET Data Services 1.5)新特性详见 http://www.cnblogs.com/webabcd/archive/2010/06/11/1756071.html
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Navigation;

using Silverlight40.MyWCFDataServiceReference;
using System.Data.Services.Client;

namespace Silverlight40.WCFDataServices
{
    public partial class Demo : Page
    {
        private NorthwindEntities _context;
        private DataServiceCollection<Category> _categories;

        public Demo()
        {
            InitializeComponent();
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            // 指定数据服务地址
            _context = new NorthwindEntities(new Uri("Service/MyWCFDataService.svc", UriKind.Relative));

            _categories = new DataServiceCollection<Category>();
            _categories.LoadCompleted += new EventHandler<LoadCompletedEventArgs>(_categories_LoadCompleted);

            // 演示如何通过 WCF Data Services 做服务端分页
            ServerPagingDemo();
        }

        // 开始异步加载 Categories 数据
        private void btnGetData_Click(object sender, RoutedEventArgs e)
        {
            gridCategory.DataContext = null;
            gridProduct.DataContext = null;

            // 加载 Categories 表中的全部数据
            var query = from c in _context.Categories select c;
            _categories.LoadAsync(query);

            btnGetData.IsEnabled = false;
        }

        // 异步加载 Categories 数据完成
        void _categories_LoadCompleted(object sender, LoadCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                if (_categories.Continuation != null)
                {
                    // 在数据服务中 Categories 被服务端分页了,所以需要不断调用 LoadNextPartialSetAsync() ,以便加载全部的 Categories 数据
                    _categories.LoadNextPartialSetAsync();
                }
                else
                {
                    gridCategory.DataContext = _categories;
                    gridCategory.SelectedIndex = 0;

                    btnGetData.IsEnabled = true;
                }
            }
            else
            {
                MessageBox.Show(e.Error.ToString());
                btnGetData.IsEnabled = true;
            }
        }

        // 开始异步加载指定 Category 下的 Products 数据
        private void gridCategory_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            Category category = gridCategory.SelectedItem as Category;

            if (category != null)
            {
                if (category.Products.Count == 0)
                {
                    category.Products.LoadCompleted += new EventHandler<LoadCompletedEventArgs>(Products_LoadCompleted);

                    try
                    {
                        // 加载实体的导航属性数据
                        category.Products.LoadAsync();
                    }
                    catch (InvalidOperationException ex)
                    {
                        MessageBox.Show(ex.ToString());
                    }
                }
                else
                {
                    gridProduct.DataContext = category.Products;
                }
            }
        }

        // 异步加载 Products 数据完成
        void Products_LoadCompleted(object sender, LoadCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                DataServiceCollection<Product> products = sender as DataServiceCollection<Product>;

                if (products.Continuation != null)
                {
                    try
                    {
                        products.LoadNextPartialSetAsync();
                    }
                    catch (InvalidOperationException ex)
                    {
                        MessageBox.Show(ex.ToString());
                    }
                }
                else
                {
                    gridProduct.DataContext = products;
                }
            }
            else
            {
                MessageBox.Show(e.Error.ToString());
            }
        }

        // 异步保存 Categories 中的被更新的数据(包括增删改),由于 Products 是 Category 的导航属性,所以相关的 Products 的数据的更新也会被保存
        private void btnSave_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                /*
                 * NorthwindEntities - 继承自 DataServiceContext,在 VS 中引用服务后会自动生成这个对象
                 *     DataServiceContext.BeginSaveChanges() - 将有变化的数据提交至数据服务端进行更新
                 *     DataServiceContext.EndSaveChanges() - 获取 BeginSaveChanges() 操作的结果,返回一个 DataServiceResponse 类型的对象
                 */

                _context.BeginSaveChanges(SaveChangesOptions.Batch, OnChangesSaved, null);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        // 数据被异步保存后
        private void OnChangesSaved(IAsyncResult result)
        {
            bool error = false;

            this.Dispatcher.BeginInvoke(() =>
            {
                try
                {
                    DataServiceResponse response = _context.EndSaveChanges(result);

                    foreach (ChangeOperationResponse changeResponse in response)
                    {
                        if (changeResponse.Error != null)
                            error = true;
                    }

                    if (!error)
                    {
                        MessageBox.Show("数据更新成功");
                    }
                    else
                    {
                        MessageBox.Show("数据更新失败");
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
            });
        }

 

        private int _pageIndex = 0;
        private int _pageSize = 3;

        // 演示如何通过 WCF Data Services 做服务端分页
        private void ServerPagingDemo()
        {
            BindOrder();

            btnNext.Click += (s, args) =>
            {
                _pageIndex++;
                BindOrder();
            };

            btnPrev.Click += (s, args) =>
            {
                _pageIndex--;
                BindOrder();
            };
        }

        private void BindOrder()
        {
            txtCurrentPageIndex.Text = "当前页索引:" + _pageIndex.ToString();

            var query = from o in _context.Orders select o;
            query = query.Skip(_pageIndex * _pageSize).Take(_pageSize);
            DataServiceCollection<Order> orders = new DataServiceCollection<Order>();
            orders.LoadAsync(query);

            orders.LoadCompleted += (s, args) =>
            {
                gridOrder.DataContext = orders;
            };
        }
    }
}

OK

源码下载:http://files.cnblogs.com/webabcd/Silverlight.rar









评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值