数据交换=>Windows_Mobile+WCF+Exchange2007 - part2
数据交换=>Windows_Mobile+WCF+Exchange2007 - part1
数据交换=>Windows_Mobile+WCF+Exchange_2007
摘要:WCF作为一个新的特征在.Net Compact Framework中得到实现。本文将基于 Exchange2007继续探讨WCF Compact特有的消息存储和转发特性(Store and Forward messaging)。这一部分将之前的调度器应用升级到支持照片共享,并结合Virtual Earth加入了定位元素。
Keywords:
WCF,Windows Mobile,.Net Compact Framework,Exchange Server 2007,Virtual Earth
(本文英文原文由marteaga发表于Opennetcf Community 原题为“Exchanging Data using Windows Mobile, Windows Communication Foundation, .NET Compact Framework and Exchange 2007”)
非常建议您先阅读前面一篇文章:Change_your_life=>Windows_Mobile+WCF+Exchange2007 - part1
加强版的调度器应用
为了用于实际的企业应用,我们把之前的调度器应用做了一些加强. 比如, 使用SQL Server 存放调度器发出的请求, 现场的服务执行终端会被打上一个GPS的标签. 你也可以使用SQL Replication存储并同步数据, 并使用WCF 来提示应用程序进行同步。
- 图片共享的应用场景
图片共享的应用允许用户分享他们最近拍摄的照片,使用WCF和Exchange来发送照片. 这里我们假设一个Windows Mobile 应用跑在两台独立的设备上,我们的桌面应用不再是调度器的角色(后面会详细介绍)。
我们假设这个应用是由于在两个希望分享近期照片的朋友之间,不过同样的主题还是可以用于一个LOB型的应用。比如一个现场的工人可以拍摄一张问题组件照片发送给中央调度器,由调度器分析并指派相应的助理或者专家到现场。
Windows Mobile端的实现
在前面的示例中,我们在桌面的应用程序中初始化了消息对象。在接下来的这个程序中,我们将会在移动设备来做这个工作。并将消息发往桌面应用以及另一个设备。
和之前的调度器应用一样,我们将使用WCFMessagingManager,XmlSerializerWrapper略有不同的是在这个例子里面我们发送的是一个PhotoData消息对象,而不是DispatchMessage。
先如下创建WCFMessagingManager:
WindowsMobileMailBinding binding = newWindowsMobileMailBinding();
m_messagingManager = newWCFMessagingManager<PhotoData>(binding, m_config.IncomingChannel);
PhotoData的定义如下:
public class PhotoData
{
privateBitmap m_bitmap = null;
public PhotoData(string filename)
{
//这里我们暂且以多伦多的纬度和经度为例
this.Latitude = 43.6919;
this.Longitude = -79.5782;
//设置文件名
FileName = filename;
SetProperties();
//设置ID
Id = Guid.NewGuid();
}
public PhotoData()
{
}
public string Comment { get; set; }
public Guid Id { get; set; }
public string FileName { get; set; }
public double Latitude { get; set; }
public double Longitude { get; set; }
public int FileSize { get; set; }
public string Base64Data { get; set; }
///<returns></returns>
public Bitmap GetBitmapImage()
{ ... }
private void SetProperties()
{ ... }
}
你可以看到, 这里 photoData有各种各样的一些属性:图片说明,文件名,纬度/经度,文件大小,Base64数据。当通过WCF发送消息的时候,我们需要确保图片被正确的转化为Base64的字符串:
private void SetProperties()
{
if (File.Exists(FileName))
{
//Grab the byte data from the file
FileStream fs = File.Open(FileName, FileMode.Open);
byte[] data = newbyte[fs.Length];
fs.Read(data, 0, data.Length);
fs.Close();
//Set the file size
FileSize = data.Length;
//convert the byte[] to base64
Base64Data = Convert.ToBase64String(data);
}
}
上述方法从PhotoData(string)的构造器中被调用并设置属性。可以看到PhotoData有两个构造器, 其中无参构造器是用于在XmlSerializerWrapper中调用XmlSerializer来反序列化XML数据. 所以当一个PhotoData对象被接收到的时候,XmlSerializer会自动反序列化数据.
PhotoData还有一个public的方法,来返回要显示的位图对象:
public Bitmap GetBitmapImage()
{
if (m_bitmap == null)
{
if (Base64Data != null)
{
byte[] imageData = Convert.FromBase64String(Base64Data);
m_bitmap = new Bitmap(new MemoryStream(imageData));
}
}
return m_bitmap;
}
在接收端只需要调用GetBitmapImage就可以显示图片了. Windows Mobile端的UI很直观,几乎无须说明,只用到了一个pictureBox和两个menuItems:
我们使用Microsoft.WindowsMobile.Forms.CameraCaptureDialog来拍摄照片(Windows Mobile 5 and later) :
using (CameraCaptureDialog ccd = newCameraCaptureDialog())
{
if (ccd.ShowDialog() == DialogResult.OK)
{
CurrentPhotoData = newPhotoData(ccd.FileName);
CurrentPhotoData.FileName = ccd.FileName;
pictureBox1.Image = newBitmap(CurrentPhotoData.FileName);
}
}
拍摄完照片,我们让PictureBox来显示刚刚拍摄的图片.然后, 我们调用WCFMessageingManager.SendMessage直接将图片发送出去:
//Send the message to the device
m_messagingManager.SendMessage(m_config.SendToEmail, m_config.OutgoingChannel, CurrentPhotoData);
//Send the message to the desktop
m_messagingManager.SendMessage(m_config.SendToEmail, m_config.OutgoingChannelDesktop, CurrentPhotoData);
桌面端的实现
桌面端只是简单的监听photaData并显示它们, UI也很简单, 使用了一个listBox来显示当前来内存中的Photodata对象, 一个pictureBox来显示图片和一个WebBrowser控件来显示Virtual Earth地图和拍摄地点.(关于Virtual Earth的集成,后文有介绍)
UI如下图所示:
当WCFMessagingManager.IncomingMessage事件被主UI处理之后,我们希望更新我们的UI, 这里我们使用了BeginInvoke:
this.BeginInvoke(newEventHandler(delegate(object sender, EventArgs ea)
{
//find the message in the internal list
var message = from tmsg in m_messagesReceived
where tmsg.Id.Equals(body.Id)
select tmsg;
if (message.Count() == 0)
{
//add the item to the list
m_messagesReceived.Add(body);
}
UpdateListbox();
}));
参数m_messagesRecevied是List<string>类型, 用作 ListBox的dataSource:
listBox1.DataSource = m_messagesReceived;
在ListBox.SelectedIndexChanged事件中, 我们显示照片以及在VE的地图上标记拍摄地点:
if (listBox1.SelectedIndex >= 0 && listBox1.SelectedIndex < m_messagesReceived.Count)
{
PhotoData pd = m_messagesReceived[listBox1.SelectedIndex];
//从Photodata中获取照片并显示
this.pictureBox1.Image = pd.GetBitmapImage();
//显示拍摄地点的标记
executeScript(ClearPushpinsScript);
executeScript(AddPushpinScript, pd.Id.ToString(),
(pd.Comment == null ? "No Comments" : pd.Comment.ToString()),
pd.Latitude, pd.Longitude);
//设置标记中心
executeScript(SetCenter, pd.Latitude, pd.Longitude);
//设置放大倍数显示
executeScript(Zoom, 18);
}
执行结果
我们用一台运行着Windows Mobile 5.0 的Palm Treo 700wx 拍摄了一张照片,并发送给桌面的应用以及一台Windows mobile 6.1 Professional的模拟器 :
Virtual Earth在桌面应用中的集成
由于我们的PhotoData包含有纬度和经度信息,自然会想到在桌面应用中将VE集成进去。这里我们选用了 WinForms Earth v2. 不过我们需要把它原来的Code稍作更新,因为它们已经很过时了。要在WinForm中使用VE我们需要做以下一些工作:
- 需要一个本地的HTML页来加载VE的地图,这个HTML 文件里面还应当包含一些javascript的函数,我们可以从.NET 的应用中去调用到。
- ComVisible(true) 特性需要被添加到你的form中,当然这个特性标签也可以被加到那个处理.NET 代码和HTML文档的通信类上,不过在此为了简便,我们直接加到form上。
- .NET中和HTMLdocument JavaScript的代码交互是通过调用WebBrowser.Document.InvokeScript方法完成的
- HTMLdocument中和.NET的交互是通过JavaScript的函数window.external.X 这里X表示在.NET代码中你的方法名。这个方法当然必须是public的. WinForms Earth V2 中有相关的示例
进一步的加强
这里我们是把坐标写死,实际上我们可以使用真是的GPS的设备,来捕获当前坐标,可以参考WM6SDK中的 GPS Sample 。在桌面端,你可以将每一个photodata对象存入SQLServer Compact Database中。当然你也可以把这些图片数据和你的Flickr 或是 facebook相册结合起来;)
- 总结
E-mail已经风靡很长时间了, 在如今的移动设备上Email也是最先实现的几个功能之一。 和Windows Mobile一起,现在我们有了direct push email 和.NET Compact Framework 3.5我们可以将email 和direct push 技术纳入到我们的Windows Mobile的应用当中去。作为开发人员,这里的Compact WCF使得我们减少了对移动设备的通信问题的烦恼,使得程序员能专注于应用程序本身,而不再是设备定址问题。
完整的代码在此处下载
Enjoy!
黄季冬
posted on 2008-08-02 12:13 J.D Huang 阅读(1672) 评论(4) 编辑 收藏 举报