在很多情况下,图像是特定于平台的。他们需要满足设备本身的尺寸和 DPI,并且需要适应应用程序的外观和感觉。对于这些情况,我会让 View 自己决定向用户显示哪些图像,可能基于 ViewModel 提供的某种状态/模式。
但是,在这些情况下,图像需要来自 ViewModel,例如,在邮件应用程序中显示的发件人缩略图的情况下。在这些情况下,我让 ViewModel 返回某种与平台无关的图像概念(例如 byte[]),然后让特定于平台的项目将其转换为他们的 UI 堆栈可以理解的东西(在 XAML 中,这个将是一个 ImageSource)。
代码看起来像这样:
便携式项目:
using System.IO;
using System.Reflection;
namespace Portable
{
public class ViewModel
{
private byte[] _image = LoadFromResource("Image.png");
public byte[] Image
{
get { return _image; }
}
private static byte[] LoadFromResource(string name)
{
using (Stream stream = typeof(ViewModel).GetTypeInfo().Assembly.GetManifestResourceStream("Portable." + name))
{
MemoryStream buffer = new MemoryStream();
stream.CopyTo(buffer);
return buffer.ToArray();
}
}
}
}
注意:您需要根据您的目标平台删除或添加 GetTypeInfo()。
在这里,我们从嵌入式资源(属性 -> 构建操作 -> 嵌入式资源)中读取数据,但您可以想象这来自网络或其他地方。
Windows Store 应用程序项目:
在 Windows Store 应用程序中,您将有一个值转换器从 byte[] -> ImageSource 转换:
using System;
using System.IO;
using Windows.Storage.Streams;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Media.Imaging;
namespace App
{
public class ByteToImageSourceValueConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
InMemoryRandomAccessStream s = new InMemoryRandomAccessStream();
byte[] bytes = (byte[])value;
Stream stream = s.AsStreamForWrite();
stream.Write(bytes, 0, bytes.Length);
stream.Flush();
stream.Seek(0, SeekOrigin.Begin);
BitmapImage source = new BitmapImage();
source.SetSource(s);
return source;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
}
在 View 后面的代码中,设置 DataContext:
DataContext = new ViewModel();
然后在 View 本身绑定到 ViewModel.Image 属性,并设置转换器:
<Page.Resources>
<local:ByteToImageSourceValueConverter x:Name="ImageConverter"/>
</Page.Resources>
<Grid >
<Image HorizontalAlignment="Left" Height="242" Margin="77,10,0,0" VerticalAlignment="Top" Width="278" Source="{Binding Image, Converter={StaticResource ImageConverter}}"/>
</Grid>