原文:与众不同 windows phone (29) - Communication(通信)之与 OData 服务通信

[索引页]
[源码下载]

与众不同 windows phone (29) - Communication(通信)之与 OData 服务通信

作者:webabcd

介绍
与众不同 windows phone 7.5 (sdk 7.1) 之通信

  • 与 OData 服务通信

示例
1、服务端(采用 Northwind 示例数据库)
NorthwindService.svc.cs

/*
* 提供 OData 服务,详细说明请参见 WCF Data Services 的相关文章:http://www.cnblogs.com/webabcd/category/181636.html
*/ 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 Web.Communication
{
// 出现异常时,返回详细的错误信息
[System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)]
public class NorthwindService : DataService<NorthwindEntities>
{
public static void InitializeService(DataServiceConfiguration config)
{
// 全部实体全部权限
config.SetEntitySetAccessRule("*", EntitySetRights.All);
// 指定服务所支持的 OData 协议的最大版本
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
}
}
}

2、客户端(ViewModel 层)
MyViewModel.cs

/*
* 调用 OData 服务的 ViewModel 层
*
* DataServiceCollection<T> - OData 服务的实体数据集合,添加、删除和更新数据时都会提供通知,继承自 ObservableCollection<T>
* Count - 实体数据集合中的实体数
* CollectionChangedCallback - 实体集合更改时调用的委托
* EntityChangedCallback - 实体更改时调用的委托
* Continuation - 是否还有下一页数据
* LoadAsync(IQueryable<T> query) - 通过指定的查询异步加载数据
* CancelAsyncLoad() - 取消异步加载请求
* LoadNextPartialSetAsync() - 加载下一页数据
* Detach() - 停止跟踪集合中的全部实体
* LoadCompleted - 异步数据加载完成后触发的事件
*
*
* DataServiceState - 服务状态
* Serialize(DataServiceContext context, Dictionary<string, Object> collections) - 序列化 DataServiceContext 对象以及页面的相关数据
* 注:引用 OData 服务后,会自动生成一个继承自 DataServiceContext 的代理类,如果需要序列化的话,则必须手动为其加上 [System.Runtime.Serialization.DataContract]
* Deserialize() - 反序列化,返回 DataServiceState 类型的数据
* Context - 相关的 DataServiceContext 对象
* RootCollections - 相关的数据
*
*
* 注:
* OData 服务的相关查询参数参见:http://msdn.microsoft.com/en-us/library/gg309461.aspx
*/ using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes; using System.ComponentModel;
using Demo.NorthwindContext;
using System.Data.Services.Client;
using System.Linq;
using System.Collections.Generic; namespace Demo.Communication.ODataClient.ViewModel
{
public class MyViewModel : INotifyPropertyChanged
{
// 引用过来的 OData 服务
private NorthwindEntities _context;
// OData 服务地址
private Uri _northwindUri = new Uri("http://localhost:15482/Communication/NorthwindService.svc/"); // 相关数据,DataServiceCollection<T> 继承自 ObservableCollection<T>
public DataServiceCollection<Category> Categories { get; private set; } public void LoadData()
{
_context = new NorthwindEntities(_northwindUri); // 实例化 DataServiceCollection<Category>,并注册相关事件
Categories = new DataServiceCollection<Category>(_context);
Categories.LoadCompleted += new EventHandler<LoadCompletedEventArgs>(Categories_LoadCompleted); // 获取全部 Categories 数据,并且一次请求带上 Categories 的所有 Products
DataServiceQuery<Category> query = _context.Categories.Expand("Products");
Categories.LoadAsync(query); NotifyPropertyChanged("Categories");
} void Categories_LoadCompleted(object sender, LoadCompletedEventArgs e)
{
if (e.Error == null)
{
// 如果服务端有分页,则继续获取直至获取完全部数据
if (Categories.Continuation != null)
Categories.LoadNextPartialSetAsync();
}
else
{
Deployment.Current.Dispatcher.BeginInvoke(delegate
{
MessageBox.Show(e.Error.ToString());
});
}
} // 新增产品数据
public void AddProduct(Product product)
{
_context.AddToProducts(product); Categories.Single(p => p.CategoryID == product.CategoryID).Products.Add(product); SaveChanges();
} // 删除产品数据
public void DeleteProduct(Product product)
{
_context.DeleteObject(product); Categories.Single(p => p.CategoryID == product.CategoryID).Products.Remove(product); SaveChanges();
} // 更新产品数据
public void UpdateProduct(Product product)
{
_context.UpdateObject(product); SaveChanges();
} public void SaveChanges()
{
// 异步向 OData 服务提交最近的数据变化
_context.BeginSaveChanges(OnChangesSaved, _context);
} private void OnChangesSaved(IAsyncResult result)
{
Deployment.Current.Dispatcher.BeginInvoke(delegate
{
_context = result.AsyncState as NorthwindEntities; try
{
// 完成数据提交
_context.EndSaveChanges(result);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
});
} // 一个异步获取数据的例子,此 Demo 没用到此方法
public void GetData()
{
// 查找 Products 里 ProductID 为 1 的数据
var query = _context.CreateQuery<Product>("Products").AddQueryOption("$filter", "ProductID eq 1"); // 异步请求 OData 服务
query.BeginExecute(p =>
{
var myQuery = p.AsyncState as DataServiceQuery<Product>; try
{
// 获取请求结果
var result = myQuery.EndExecute(p).First();
// 更新数据
_context.UpdateObject(result);
// 将更新后的结果提交到 OData 服务
SaveChanges();
}
catch (Exception ex)
{
Deployment.Current.Dispatcher.BeginInvoke(delegate
{
MessageBox.Show(ex.ToString());
});
}
}, query);
} // 序列化当前数据,Deactivated 保存此值到应用程序状态,参见 App.xaml.cs
public string GetState()
{
var dict = new Dictionary<string, object>();
dict["categories"] = Categories; return DataServiceState.Serialize(_context, dict);
} // 恢复数据,当从 tombstone 状态进入 Activated 时,则从应用程序状态中恢复数据,参见 App.xaml.cs
public void RestoreState(string appState)
{
Dictionary<string, object> dict; if (!string.IsNullOrEmpty(appState))
{
DataServiceState state = DataServiceState.Deserialize(appState); // 获取相关数据
var context = state.Context as NorthwindEntities;
dict = state.RootCollections;
DataServiceCollection<Category> categories = dict["Categories"] as DataServiceCollection<Category>; // 恢复相关数据
_context = context;
Categories = categories;
Categories.LoadCompleted += new EventHandler<LoadCompletedEventArgs>(Categories_LoadCompleted);
NotifyPropertyChanged("Categories");
}
} public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string propertyName)
{
var propertyChanged = PropertyChanged;
if (propertyChanged != null)
propertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}

3、客户端(View 层)
App.xaml

<Application
x:Class="Demo.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" xmlns:odataViewModel="clr-namespace:Demo.Communication.ODataClient.ViewModel"> <Application.Resources> <odataViewModel:MyViewModel x:Key="ODataViewModel" /> </Application.Resources> </Application>

App.xaml.cs

        private void Application_Activated(object sender, ActivatedEventArgs e)
{
// 从 tombstone 状态返回,则恢复相关数据,参见:“调用 OData 服务”
if (!e.IsApplicationInstancePreserved)
{
if (PhoneApplicationService.Current.State.ContainsKey("categoriesState"))
{
var vm = App.Current.Resources["ODataViewModel"] as MyViewModel;
string categoriesState = PhoneApplicationService.Current.State["categoriesState"] as string; vm.RestoreState(categoriesState);
}
}
} private void Application_Deactivated(object sender, DeactivatedEventArgs e)
{
// 保存相关数据,参见:“调用 OData 服务”
var vm = App.Current.Resources["ODataViewModel"] as MyViewModel;
PhoneApplicationService.Current.State["categoriesState"] = vm.GetState();
}

Demo.xaml

<phone:PhoneApplicationPage
x:Class="Demo.Communication.ODataClient.Demo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
mc:Ignorable="d" d:DesignHeight="696" d:DesignWidth="480"
shell:SystemTray.IsVisible="True" DataContext="{Binding Source={StaticResource ODataViewModel}}"
xmlns:controls="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls"> <phone:PhoneApplicationPage.Resources>
<DataTemplate x:Key="item">
<ListBox ItemsSource="{Binding Products}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Width="460" HorizontalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5*" />
<ColumnDefinition Width="5*" />
</Grid.ColumnDefinitions> <StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<TextBlock Text="{Binding ProductName}" />
<TextBlock Text="{Binding UnitPrice}" Margin="10 0 0 0" />
</StackPanel> <StackPanel Orientation="Horizontal" Grid.Column="1" HorizontalAlignment="Right">
<Button x:Name="btnUpdate" Content="更新" Click="btnUpdate_Click" />
<Button x:Name="btnDelete" Content="删除" Click="btnDelete_Click" />
</StackPanel>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DataTemplate>
<DataTemplate x:Key="header">
<TextBlock Text="{Binding CategoryName}" />
</DataTemplate>
</phone:PhoneApplicationPage.Resources> <Grid x:Name="LayoutRoot" Background="Transparent">
<controls:Pivot x:Name="pivot"
Title="产品列表"
ItemTemplate="{StaticResource item}"
HeaderTemplate="{StaticResource header}"
ItemsSource="{Binding Categories}">
</controls:Pivot>
</Grid> <phone:PhoneApplicationPage.ApplicationBar>
<shell:ApplicationBar Mode="Default" IsVisible="True">
<shell:ApplicationBarIconButton x:Name="btnAd" IconUri="/ApplicationBarDemo/Assets/appbar.add.rest.png" Text="添加" Click="btnAd_Click" />
</shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar> </phone:PhoneApplicationPage>

Demo.xaml.cs

/*
* 调用 OData 服务的 View 层
*/ 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 Microsoft.Phone.Controls; using Demo.Communication.ODataClient.ViewModel;
using Demo.NorthwindContext; namespace Demo.Communication.ODataClient
{
public partial class Demo : PhoneApplicationPage
{
public Demo()
{
InitializeComponent(); this.Loaded += new RoutedEventHandler(Demo_Loaded);
} void Demo_Loaded(object sender, RoutedEventArgs e)
{
// 加载数据
var vm = App.Current.Resources["ODataViewModel"] as MyViewModel;
vm.LoadData();
} private void btnDelete_Click(object sender, RoutedEventArgs e)
{
var product = (sender as Button).DataContext as Product; // 删除指定的产品数据
var vm = App.Current.Resources["ODataViewModel"] as MyViewModel;
vm.DeleteProduct(product);
} private void btnUpdate_Click(object sender, RoutedEventArgs e)
{
// 更新指定的产品数据
var product = (sender as Button).DataContext as Product;
product.UnitPrice = 8.88m; var vm = App.Current.Resources["ODataViewModel"] as MyViewModel;
vm.UpdateProduct(product);
} private void btnAd_Click(object sender, EventArgs e)
{
// 在指定的类别下添加一个新的产品数据
var category = pivot.SelectedItem as Category; Product product = new Product();
product.CategoryID = category.CategoryID;
product.ProductName = "测试" + new Random().Next(, );
product.UnitPrice = 6.66m;
product.Discontinued = false; var vm = App.Current.Resources["ODataViewModel"] as MyViewModel;
vm.AddProduct(product);
}
}
}

OK
[源码下载]

与众不同 windows phone (29) - Communication(通信)之与 OData 服务通信的更多相关文章

  1. 与众不同 windows phone (33) - Communication(通信)之源特定组播 SSM(Source Specific Multicast)

    原文:与众不同 windows phone (33) - Communication(通信)之源特定组播 SSM(Source Specific Multicast) [索引页][源码下载] 与众不同 ...

  2. 与众不同 windows phone (32) - Communication(通信)之任意源组播 ASM(Any Source Multicast)

    原文:与众不同 windows phone (32) - Communication(通信)之任意源组播 ASM(Any Source Multicast) [索引页][源码下载] 与众不同 wind ...

  3. 与众不同 windows phone (31) - Communication(通信)之基于 Socket UDP 开发一个多人聊天室

    原文:与众不同 windows phone (31) - Communication(通信)之基于 Socket UDP 开发一个多人聊天室 [索引页][源码下载] 与众不同 windows phon ...

  4. 与众不同 windows phone (30) - Communication(通信)之基于 Socket TCP 开发一个多人聊天室

    原文:与众不同 windows phone (30) - Communication(通信)之基于 Socket TCP 开发一个多人聊天室 [索引页][源码下载] 与众不同 windows phon ...

  5. RRiBbit,一个事件总线.基于spring配置不同服务通信!

    1.何为RRiBbit? *一种开源事件总线技术,能够让模块(组件)之间双向通讯,也被称为请求相应总线(request-response-bus),使用简单,相对其他框架来说,RRiBbit只需要加个 ...

  6. 与众不同 windows phone (46) - 8.0 通信: Socket, 其它

    [源码下载] 与众不同 windows phone (46) - 8.0 通信: Socket, 其它 作者:webabcd 介绍与众不同 windows phone 8.0 之 通信 Socket ...

  7. 与众不同 windows phone 8.0 & 8.1 系列文章索引

    [源码下载] [与众不同 windows phone 7.5 (sdk 7.1) 系列文章索引] 与众不同 windows phone 8.0 & 8.1 系列文章索引 作者:webabcd ...

  8. 与众不同 windows phone (39) - 8.0 联系人和日历

    [源码下载] 与众不同 windows phone (39) - 8.0 联系人和日历 作者:webabcd 介绍与众不同 windows phone 8.0 之 联系人和日历 自定义联系人存储的增删 ...

  9. 背水一战 Windows 10 (29) - 控件(文本类): RichTextBlock, RichTextBlockOverflow, RichEditBox

    [源码下载] 背水一战 Windows 10 (29) - 控件(文本类): RichTextBlock, RichTextBlockOverflow, RichEditBox 作者:webabcd ...

随机推荐

  1. Java中的位运算符、移位运算

    一.位运算 Java中有4个位运算,它们的运算规则如下: (1)按位与 (&)  :两位全为1,结果为1,否则为0: (2)按位或  (|)   :两位有一个为1,结果为1,否则为0: (3) ...

  2. java--join方法

    package MyTest; class TestDemo implements Runnable { public void run() { int i = 0; for (int j = 0; ...

  3. 知识点1-1:什么是ASP.NET MVC

    ASP.NET MVC是微软.NET平台上的一个Web开发框架,它为开发者提供了一种构建结构良好的Web应用程序的方式.自2007年首次公布预览以来,作为Web Form的替代品,ASP.NET MV ...

  4. java正则去掉小数点后多余0

    需求:已知字符串为一数字字符形式,多为float,double转换过来,将其后多余的0与.去掉. package test; /** * 去掉多余的.与0 * @author Hust * @Time ...

  5. Hibernate 3中如何获得库表所有字段的名称

    15问:Hibernate 3中如何获得库表所有字段的名称 答:可以使用以下的程序获得. Configuration conf = new Configuration(); conf.configur ...

  6. 公司需求知识学习-WCF

    一.概述 Windows Communication Foundation(WCF)是由微软发展的一组数据通信的应用程序开发接口,可以翻译为Windows通讯接口,它是.NET框架的一部分.由 .NE ...

  7. JPA相关知识点滴--持续更新中.....

    Java 持久化(JPA)  •Java EE 5 在EJB 3.0 中包含JPA 1.0 •参考实现:TopLink Essentials •Java EE 6 包含JPA 2.0 •参考实现:Ec ...

  8. Linux中处理需要传输的IP报文流程

    本文主要讲解了Linux中处理需要传输的IP报文流程,使用的内核的版本是2.6.32.27 为了方便理解,本文采用整体流程图加伪代码的方式对Linux中处理需要传输的IP报文流程进行了讲解,希望可以对 ...

  9. load data 方式导入的数据不可以用binlog日志进行恢复,因为binlog里面不产生insert sql语句。

    QQ群里面有人问起这个问题:    用load data 导入数据的时候,在binlog文件中记录的不是insert 语句,这样的话,如果用load data 导入数据,当需要恢复数据库的时候  bi ...

  10. HDU 3790 最短路径问题 (SPFA)

    转载请注明出处:http://blog.csdn.net/a1dark 分析:比一般最短路多了一个花费.多加一个判断即可.用的SPFA.这道题让我搞清楚了以前定义INF为啥爆的问题.受益颇多. #in ...