问题
In my UWP app i store images in an SQLite db in form of byte[]. Then as i retrieve my objects from the db i bind them to a GridView data template which has an Image control. As i cant bind the Image's Source directly to the array, so i have created a BitmapImage property in my object's class to bind the Image control to:
public BitmapImage Icon
{
get
{
using (var stream = new MemoryStream(icon))
{
stream.Seek(0, SeekOrigin.Begin);
var img = new BitmapImage();
img.SetSource(stream.AsRandomAccessStream());
return img;
}
}
}
The problem is, my app hangs on the img.SetSource line. After some experimenting, i have found that this problem can be overcome with a second MemoryStream:
public BitmapImage Icon
{
get
{
using (var stream = new MemoryStream(icon))
{
stream.Seek(0, SeekOrigin.Begin);
var s2 = new MemoryStream();
stream.CopyTo(s2);
s2.Position = 0;
var img = new BitmapImage();
img.SetSource(s2.AsRandomAccessStream());
s2.Dispose();
return img;
}
}
}
For some reason it works, does not hang. I wonder why? And how to deal with this situation properly? Thanks!
回答1:
i'll suggest you use the IValueConverter interface before showing the image in your app.
class ImageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
if (value == null || !(value is byte[]))
return null;
using (InMemoryRandomAccessStream ms = new InMemoryRandomAccessStream())
{
using (DataWriter writer = new DataWriter(ms.GetOutputStreamAt(0)))
{
writer.WriteBytes((byte[])value);
writer.StoreAsync().GetResults();
}
var image = new BitmapImage();
image.SetSource(ms);
return image;
}
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
回答2:
I use an extension method that I use into the converter:
public static BitmapImage AsBitmapImage(this byte[] byteArray)
{
if (byteArray != null)
{
using (var stream = new InMemoryRandomAccessStream())
{
stream.WriteAsync(byteArray.AsBuffer()).GetResults();
// I made this one synchronous on the UI thread;
// this is not a best practice.
var image = new BitmapImage();
stream.Seek(0);
image.SetSource(stream);
return image;
}
}
return null;
}
回答3:
Why not to use Base64? Save Base64 Image in sqlite database column and bind it to Image control easily.
<Image Source="{Binding Path=imagedata}" Height="120" Width="120"></Image>
it is much easier to bind image inside Gridview from sqlite db.
回答4:
I've had an issues printing images loading from RandomAccessStreams until I found this. They load fine in the app for visual but would hang the UI when generating print previews dynamically.
Conversion works perfectly, cheers.
private BitmapImage ConvertImage(string str) {
byte[] imgData = Convert.FromBase64String(str);
using (InMemoryRandomAccessStream ms = new InMemoryRandomAccessStream())
{
using (DataWriter writer = new DataWriter(ms.GetOutputStreamAt(0)))
{
writer.WriteBytes(imgData);
writer.StoreAsync.GetResults();
}
BitmapImage result = new BitmapImage();
result.SetSource(ms);
return result;
}}
来源:https://stackoverflow.com/questions/37384235/uwp-bitmapimage-setsource-from-memorystream-hangs