Silverlight 2 打造饭否Show

在Silverlight 1.1的时候,我就像用Silverlight设计一个饭否Show,无奈1.1时代貌似只能通过Web Services来获取跨域的数据,我认为这是一种别扭的开发方式,再加上1.1对中文并不友好,所以就改用Flash实现了这个饭否Show。
Silverlight 2终于解决了上述的两个问题,支持跨域获取数据,支持中文显示,于是我迫不及待的尝试着开发了一个饭否Show(在Silverlight 2 beta SDK 发布的几日后开始开发,开发完成后便忘记了,-___-|||),下面来简要的分享一下开发过程,也望各位Silverlight前辈不吝指教。

UI

UI的界面如下图所示:
Silverlight 2 打造饭否Show_第1张图片
UI采用Blend 2.5和Design设计。
如果设计简单的Silverlight界面,那么Blend足矣,但稍复杂的,比如上图中的波浪渐变效果,Blend就无能为力了,而这正是Design的拿手本领。
Design的使用方法就不介绍了,设计完毕后,导出为Silverlight画布,然后我们copy需要的XAML节点即可。
具体的XAML内容就不在此展示了,文末我提供了本文的代码下载,有兴趣的朋友可以下载查看。

饭否API

从上图来分析,我们只用到了饭否中的两部分信息:我的信息和我的消息。
在 饭否API中,获取这两部分数据的方法如下:
获取用户信息:
http://api.fanfou.com/users/show/ 用户ID.xml
获取用户消息:
http://api.fanfou.com/statuses/user_timeline/ 用户ID.rss
那么根据饭否提供的API,我编写了下面两个类:
饭否API类
using System;
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.IO;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using System.Collections.Generic;

namespace SilverlightFanShow
{
    
/**//// 
    
/// 饭否用户
    
/// 

    public class FanfouUser
    
{
        
/**//// 
        
/// 用户头像的URL
        
/// 

        public Uri ImageURL{get;set;}

        
/**//// 
        
/// 用户的显示名称
        
/// 

        public string Name{get;set;}

        
/**//// 
        
/// 用户的饭否链接地址
        
/// 

        public Uri URL{get;set;}

        
/**//// 
        
/// 从Stream加载饭否用户实例
        
/// 

        
/// 
        
/// 

        public static FanfouUser Load(Stream stream)
        
{
            FanfouUser user 
= new FanfouUser();

            
try
            
{
                XmlReader reader 
= XmlReader.Create(stream);
                XElement doc 
= XElement.Load(reader);

                user.ImageURL 
= new Uri(doc.Descendants("profile_image_url").FirstOrDefault().Value);
                user.Name 
= doc.Descendants("name").FirstOrDefault().Value;
                user.URL 
= new Uri(doc.Descendants("url").FirstOrDefault().Value);
            }

            
catch { }

            
return user;
        }


        
/**//// 
        
/// 默认构造函数
        
/// 

        public FanfouUser()
        
{
            
this.ImageURL = new Uri("http://avatar.fanfou.com/s0/00/4q/py.jpg?1183096447");
            
this.Name = "Windie";
            
this.URL = new Uri("http://fanfou.com/笑煞天");
        }

    }


    
/**//// 
    
/// 饭否消息
    
/// 

    public class FanfouMessage
    
{
        
/**//// 
        
/// 饭否消息的GUID(注:并不是.NET里的GUID)
        
/// 

        public string GUID getset; }

        
/**//// 
        
/// 饭否消息本体
        
/// 

        public string Message getset; }

        
/**//// 
        
/// 饭否消息的发布时间
        
/// 

        public DateTime Time getset; }

        
/**//// 
        
/// 从Stream加载饭否消息列表
        
/// 

        
/// 
        
/// 

        public static List<FanfouMessage> Load(Stream stream)
        
{
            List
<FanfouMessage> msgList = new List<FanfouMessage>();

            
try
            
{
                XmlReader reader 
= XmlReader.Create(stream);
                XElement doc 
= XElement.Load(reader);

                IEnumerable
<XElement> msgs = from item in doc.Descendants("item")
                                             select item;
                
foreach (XElement item in msgs)
                
{
                    FanfouMessage msg 
= new FanfouMessage();
                    msg.GUID 
= item.Descendants("guid").FirstOrDefault().Value;
                    msg.Message 
= item.Descendants("title").FirstOrDefault().Value;
                    msg.Time 
= DateTime.Parse(item.Descendants("pubDate").FirstOrDefault().Value);
                    msgList.Add(msg);
                }

            }
catch{ }

            
return msgList;
        }


        
/**//// 
        
/// 默认构造函数
        
/// 

        public FanfouMessage()
        
{
            
this.GUID = Guid.NewGuid().ToString();
            
this.Message = "欢迎使用Windie Chai设计的Silverlight饭否Show。";
            
this.Time = DateTime.Now;
        }

    }

}

传入参数

其实我设计这个饭否Show并不是只为了给我一个人使用,那么如何让每位朋友都可以把它变成自己的饭否Show呢?
那么必然要使Silverlight能够接受参数。
在做Flash开发时,可以在HTML中通过Object的“FlashVars”参数来向Flash传递参数列表,在Silverlight中我们同样可以这样做。
通过给“ InitParams”参数赋值,我们就可以向Silverlight传递参数了。
给“ InitParams”参数赋值的方法如下:
Silverlight的HTML代码块
<object type="application/x-silverlight-2-b1" height="140" width="160" data="data:application/x-oleobject;base64,QfXq3+HzJEysrJnDBxUISgAIAACJEAAAeA4AABAAAAAjAEYARgBGAEYARgBGAAAAAAAAAAAAAAB4AAAAaAB0AHQAcAA6AC8ALwBmAGkAbABlAHMALgBjAG4AYgBsAG8AZwBzAC4AYwBvAG0ALwB4AGkAYQBvAHMAaABhAHQAaQBhAG4ALwBzAGkAbAB2AGUAcgBsAGkAZwBoAHQAZgBhAG4AcwBoAG8AdwAuAHgAYQBwAAAAPAAAAAAAAAAmAAAAbwBuAFMAaQBsAHYAZQByAGwAaQBnAGgAdABFAHIAcgBvAHIAAAAAAAAAAAAAAAAAAAAOAAAASQBEAD0AEXtecSlZAAAAAAAAAQAAAAAAAAAAAAAAAAAAAA==">
<param name="source" value="http://files.cnblogs.com/xiaoshatian/silverlightfanshow.xap"/>
<param name="onerror" value="onSilverlightError"/>
<param name="background" value="#FFFFFF"/>
<param name="InitParams" value="ID=笑煞天"/>
<param name="EnableHtmlAccess" value="true" /> 
<href="http://go.microsoft.com/fwlink/?LinkID=108182" style="text-decoration: none;">
<img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style: none"/>
a>object>

仅仅把ID参数传入到Silverlight中是不够的,我们还需要在Silverlight中接收这个参数,并做进一步处理。
我们打开Silverlight项目中的App.xaml,为其Application_Startup事件添加如下代码:
Application_Startup
private void Application_Startup(object sender, StartupEventArgs e)
        
{
            
string id = "笑煞天";
            
if(e.InitParams.Keys.Contains("ID"))
                id 
= e.InitParams["ID"];
            
this.RootVisual = new Page(id);
        }
要注意的是Page默认并没有带有一个String参数的构造函数,所以我们接下来还需要为Page类添加这一构造函数重载。

Page.xaml.cs

最后,我们开始编写最关键的代码。我将在Page.xaml.cs中添加方法或事件来调用饭否API、获取用户的信息和消息列表、实现上一条下一条的跳转等。
具体的代码并不难以理解,不再详细解释,大家看注释便好:
Page.xaml.cs代码
using System;
using System.Collections.Generic;
using System.Linq;
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.Net;
using System.IO;
using System.Xml;
using System.Xml.Linq;
using System.Threading;
using System.Windows.Browser;

namespace SilverlightFanShow
{
    
public partial class Page : UserControl
    
{
        
//饭否用户ID
        private string userID;
        
//饭否用户
        private FanfouUser user;

        
//当前消息
        private FanfouMessage currentMessage;

        
//消息列表
        private List<FanfouMessage> messageList;

        
public Page(string id)
        
{
            
this.userID = id;
            InitializeComponent();
        }


        
/**//// 
        
/// 布局加载事件
        
/// 

        
/// 
        
/// 

        private void LayoutRoot_Loaded(object sender, RoutedEventArgs e)
        
{
            
//加载用户信息
            Uri userUrl = new Uri("http://api.fanfou.com/users/show/"
                
+ this.userID
                
+ ".xml");
            WebRequest userRequest 
= WebRequest.Create(userUrl);
            userRequest.BeginGetResponse(
new AsyncCallback(GetUserInfo), userRequest);

            
//加载用户消息
            Uri msgUrl = new Uri("http://api.fanfou.com/statuses/user_timeline/"
                
+ this.userID
                
+ ".rss");
            WebRequest msgRequest 
= WebRequest.Create(msgUrl);
            msgRequest.BeginGetResponse(
new AsyncCallback(GetMessages), msgRequest);
        }


        
/**//// 
        
/// 获取用户信息
        
/// 

        
/// 

        void GetUserInfo(IAsyncResult asyncResult)
        
{
            WebRequest request 
= asyncResult.AsyncState as WebRequest;
            WebResponse response
= request.EndGetResponse(asyncResult);
            Stream stream 
= response.GetResponseStream();

            user 
= FanfouUser.Load(stream);

            
//反映到UI
            this.pic.SetValue(Image.SourceProperty, user.ImageURL);
            
this.userName.Text = user.Name;

        }


        
/**//// 
        
/// 获取用户消息
        
/// 

        
/// 

        void GetMessages(IAsyncResult asyncResult)
        
{
            WebRequest request 
= asyncResult.AsyncState as WebRequest;
            WebResponse response 
= request.EndGetResponse(asyncResult);
            Stream stream 
= response.GetResponseStream();

            messageList 
= FanfouMessage.Load(stream);

            
//反映到UI
            if(messageList.Count > 1)
                
this.SetMessage(messageList[0]);

        }


        
/**//// 
        
/// 设置当前消息
        
/// 

        
/// 

        private void SetMessage(FanfouMessage message)
        
{
            
//去掉消息正文前边的用户名
            string msg = message.Message.Substring(message.Message.IndexOf(''+ 1);
            
//如果消息正文过长,截短之
            if (msg.Length > 50)
                msg 
= msg.Substring(050+ "";
            
this.txt.Text = msg;
            
this.time.Text = message.Time.ToShortDateString();
            
this.currentMessage = message;
        }


        
/**//// 
        
/// 下一条消息按钮按下事件
        
/// 

        
/// 
        
/// 

        private void btnNext_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        
{
            
int msgIndex = messageList.IndexOf(currentMessage);
            
if (msgIndex + 1 < messageList.Count)
                SetMessage(messageList[msgIndex 
+ 1]);
            
else if(messageList.Count > 0)
                SetMessage(messageList[
0]);
        }


        
/**//// 
        
/// 下一条消息按钮按下事件
        
/// 

        
/// 
        
/// 

        private void btnPrev_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        
{
            
int msgIndex = messageList.IndexOf(currentMessage);
            
if (msgIndex > 0)
                SetMessage(messageList[msgIndex 
- 1]);
            
else if (messageList.Count > 0)
                SetMessage(messageList[messageList.Count 
- 1]);
        }


        
/**//// 
        
/// 头像点击事件
        
/// 

        
/// 
        
/// 

        private void goToFanfou(object sender, MouseButtonEventArgs e)
        
{
            
//打开用户的饭否页面
            HtmlPage.Window.Navigate(this.user.URL, "_blank");
        }

    }

}

预览

Get Microsoft Silverlight
如果你也想要在你的blog中添加这个Widget,那么,Copy上面的HTML代码,修改ID就可以了。

源码下载

点击下载源码包(包括Visual Studio Solution和Expression Design文件)

你可能感兴趣的:(ui)