对于许多情况,图像是特定于平台的。它们需要考虑设备本身的大小和DPI,并且需要与应用程序的外观和感觉相匹配。在这些情况下,我会让视图本身决定向用户显示哪些图像,可能基于 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商店应用程序项目:
在Windows商店应用程序中,您需要一个值转换器将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()
然后在视图中绑定到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>