您的位置:首页 > 其它

人间风景开发日志 – 2 <DataModel,ViewModel>

2010-02-03 16:26 253 查看
Data Model

数据模型基本上算是一个人间API数据模型的简单封装,使用人间API的XML版本,并使用LINQ to XML读取数据。

namespace RenjianImageViewer.DataModel
{
class UserModel
{
private long id;

public string NickName { get; private set; }
public string UserName { get; private set; }
public string Gender { get; private set; }
public string Avater { get; private set; }

public UserModel(string xmlString) :
this(XElement.Parse(xmlString))
{
}

public UserModel(XElement userElement)
{
id = (long)userElement.Element("id");

NickName = userElement.Element("name").Value;
UserName = userElement.Element("screen_name").Value;
Avater = userElement.Element("profile_image_url").Value;
Gender = userElement.Element("gender").Value == "1" ? "DeepSkyBlue" : "Pink";
}
}
}

Gender这个地方采取了特殊处理,因为User的GUI是用DataModel直接绑定的,所以这里我先偷了个懒,直接放上了界面颜色数据,此处比较好的做法是做一个ValueConverter来处理。这算是一个Todo Item吧。

View Model

View Model层有两个重要的用来和UI绑定的类,一个是RenjianViewModel,另一个是ImageViewModel。

RenjianViewModel是一个General的ViewModel,包含了对其他各个DataModel,ViewModel以及Command的引用,它是用来和整个窗体的DataContext绑定的。

ImageViewModel是图片的ViewModel。因为严格来说,图片并不是一个数据模型,而我又希望能有一个business object来对图片进行统一管理,其中还包含了很多显示上的tricks,所以这边在ViewModel层单独创建了一个ImageViewModel。

另外一个辅助的ViewModel类是SavingStateViewModel,它用来和UI的Save状态绑定。当用户选择保存喜欢的图片到本地时,会显示一个正在save的层,这个层上面的数据就是从这个ViewModel绑定中得到的。

下面分别就两个比较重要的ViewModel类谈一下一些实现上的tricks。

RenjianViewModel

这个类没什么好说的,一堆对其他ViewModel和DataModel的引用而已,只是有一个方法要解释一下:

public void UpdateImagesIsLocalStatus()
{
long temp = 0;
var conversitionIDs = from imageModel in ConversitionImages
select imageModel.StatusID;

var idList = conversitionIDs.ToList();

foreach (var image in Images)
{
if (idList.Contains(image.StatusID))
{
image.IsLocal = true;
idList.Remove(image.StatusID);
if (idList.Count == 0)
{
break;
}
}
}
}

这个方法是用来更新文件的本地存储状态的。

当你喜欢的图片被保存到本地之后,图片显示会使用本地的图片,从而提高速度,而图片列表中的thumbnail下方也会显示一个indicator来提示用户。这个方法就是来更新这个状态的。

为什么需要这个方法呢,因为在保存整个conversation的图片的时候,要在下面的列表中更新相关图片的状态,但是conversation图片列表的ImageViewModel全部是新建的,跟下面完整列表的ImageViewModel没有关系,所以需要在这里做一个check,保证所有在main list的ImageViewModel的状态都得到更新。为什么不直接在conversation图片列表中引用main list的ImageViewModel呢?因为在conversation图片列表出来的时候,下面的图片有可能还没有加载,与其部分同步,还不如直接分开,长痛不如短痛嘛。

ImageViewModel

这个ViewModel很复杂,甚至超过了我预期的庞大。

因为Windows Vista之后Microsoft采用了WIC来显示图片,WPF也是如此。而这个组件是具有设备无关特性的,说白了就是DPI相关的,也就是平时在Windows XP上看很正常的图片,如果DPI设置不对的话,在WPF的图片组件上显示就是变型失真。所以里面采用了一系列的tricky来fix这个问题。

System.Windows.Controls.Image imageControl = new System.Windows.Controls.Image();
BitmapImage image = new BitmapImage();
image.DownloadCompleted += (s, e) =>
{
imageControl.MaxWidth = image.PixelWidth;
imageControl.MaxHeight = image.PixelHeight;
};
image.BeginInit();
image.UriCachePolicy = new System.Net.Cache.RequestCachePolicy(System.Net.Cache.RequestCacheLevel.CacheIfAvailable);
image.CacheOption = BitmapCacheOption.OnDemand;
image.CreateOptions = BitmapCreateOptions.IgnoreColorProfile;
image.DownloadFailed += new EventHandler<System.Windows.Media.ExceptionEventArgs>(image_DownloadFailed);
image.UriSource = new Uri(ImageUrl);
image.EndInit();
if (!image.IsDownloading)
{
imageControl.MaxWidth = image.PixelWidth;
imageControl.MaxHeight = image.PixelHeight;
}
try
{
imageControl.Stretch = System.Windows.Media.Stretch.Uniform;
imageControl.StretchDirection = StretchDirection.Both;

imageControl.Source = image;
result = imageControl;
}
catch
{
return null;
}

还有一个问题是WPF至今没有办法处理gif动画,所以在ImageViewModel里面,我又用了一系列的tricky来处理gif动画的渲染。

if (string.Compare(".gif", Path.GetExtension(ImageUrl), true) == 0)
{
GIFImageControl g = new GIFImageControl();
g.Stretch = System.Windows.Media.Stretch.Uniform;
g.StretchDirection = StretchDirection.Both;
g.AnimatedImageControl(ImageUrl);
result = g;
}

GIFImageControl这个第三方的类处理了gif的动画问题,不过这里又引入了两个还没有解决的问题。

第一个是因为GIFImageControl这个类并不是标准的WPF Image类,所以它失去了stretch的功能,那就是说,所有gif的图片都不能在RIV上拉伸,而只能以原始大小显示。

第二个是,这个类本来只需要用来处理包含动画的gif,但是目前只采用了文件后缀判断,所以不包含动画的gif也会用这个类来渲染,而某些被强制改了后缀的gif动画却不能得到显示。

好了,DataModel和ViewModel的大致介绍就这么多,下一篇是关于GUI的实现的描述。

本篇对应代码下载:#53865

相关文章:

人间风景(Renjian Image Viewer, RIV)最新版本预览

人间风景开发日志 – 1 <介绍,文件结构>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐