数据交换=>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我们需要做以下一些工作:

  1. 需要一个本地的HTML页来加载VE的地图,这个HTML 文件里面还应当包含一些javascript的函数,我们可以从.NET 的应用中去调用到。
  2. ComVisible(true) 特性需要被添加到你的form中,当然这个特性标签也可以被加到那个处理.NET 代码和HTML文档的通信类上,不过在此为了简便,我们直接加到form上。
  3. .NET中和HTMLdocument JavaScript的代码交互是通过调用WebBrowser.Document.InvokeScript方法完成的
  4. 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  阅读(1671)  评论(4编辑  收藏  举报