『听风且吟』
倚楼听风雨,淡看江湖路...... 不用怀疑了,“笑煞天”和“Windie Chai”都是在下的马甲。
社区
首页
新随笔
联系
管理
订阅
随笔- 97 文章- 0 评论- 628
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的界面如下图所示:
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
{
/**/
///
<summary>
///
饭否用户
///
</summary>
public
class
FanfouUser
{
/**/
///
<summary>
///
用户头像的URL
///
</summary>
public
Uri ImageURL
{
get
;
set
;}
/**/
///
<summary>
///
用户的显示名称
///
</summary>
public
string
Name
{
get
;
set
;}
/**/
///
<summary>
///
用户的饭否链接地址
///
</summary>
public
Uri URL
{
get
;
set
;}
/**/
///
<summary>
///
从Stream加载饭否用户实例
///
</summary>
///
<param name="stream"></param>
///
<returns></returns>
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;
}
/**/
///
<summary>
///
默认构造函数
///
</summary>
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/笑煞天
"
);
}
}
/**/
///
<summary>
///
饭否消息
///
</summary>
public
class
FanfouMessage
{
/**/
///
<summary>
///
饭否消息的GUID(注:并不是.NET里的GUID)
///
</summary>
public
string
GUID
{
get
;
set
; }
/**/
///
<summary>
///
饭否消息本体
///
</summary>
public
string
Message
{
get
;
set
; }
/**/
///
<summary>
///
饭否消息的发布时间
///
</summary>
public
DateTime Time
{
get
;
set
; }
/**/
///
<summary>
///
从Stream加载饭否消息列表
///
</summary>
///
<param name="stream"></param>
///
<returns></returns>
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;
}
/**/
///
<summary>
///
默认构造函数
///
</summary>
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"
/>
<
a
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();
}
/**/
///
<summary>
///
布局加载事件
///
</summary>
///
<param name="sender"></param>
///
<param name="e"></param>
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);
}
/**/
///
<summary>
///
获取用户信息
///
</summary>
///
<param name="asyncResult"></param>
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;
}
/**/
///
<summary>
///
获取用户消息
///
</summary>
///
<param name="asyncResult"></param>
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
]);
}