Reputation: 13
I use BitmapImage
when I display avatars in my UWP app. Sometimes the avatars display wrong images (sometimes wrong size and sometimes even displaying images that I have never used in my app).
I have been googling around for a while and found few people having the same problem but none of them is solved. For example, this and this.
The following is the code in my app:
.xaml
<Image>
<Image.Source>
<BitmapImage UriSource="{x:Bind Patient.Gender, Mode=OneWay, Converter={StaticResource GenderToAvatarConverter}}" />
</Image.Source>
</Image>
GenderToAvatarConverter.cs
public sealed class GenderToAvatarConverter : IValueConverter
{
object IValueConverter.Convert(object value, Type targetType, object parameter, string language)
{
var imagePath = "ms-appx:///Assets/Avatar/Default.png";
if ((string)value == Gender.MALE.ToString())
{
imagePath = "ms-appx:///Assets/Avatar/Man.png";
}
else if((string)value == Gender.FEMALE.ToString())
{
imagePath = "ms-appx:///Assets/Avatar/Woman.png";
}
return new Uri(imagePath);
}
object IValueConverter.ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
It would be highly appreciated if someone can solve this problem or how to reproduce it.
Upvotes: 1
Views: 218
Reputation: 646
Heres a way I found to reproduce it.
I have an application where there are users, and a user can have images. When you upload an image, it is saved as 0.png. The BitmapImage loads this, and displays it. Then I delete the image, so the images folder is empty. I then add a new image, which is saved as 0.png. The two images are different, but the paths are the same, and the BitmapImage control continues to display the same image.
From this, I assume that when you create a BitmapImage from a path, it first checks somewhere else to see if the image has already been created, and uses the cache instead. (I also noticed you can only create a BitmapImage on the UI thread).
To work around this, I found you can create a new BitmapImage, and load it from a stream, and the image will not be found in the cache.
Just add a converter:
public class ImageToBitmapImageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string culture)
{
BitmapImage bitmapImage = new BitmapImage();
if (value is Image)
{
Image image = (Image)value;
using (MemoryStream memoryStream = new MemoryStream())
{
image.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Jpeg);
memoryStream.Position = 0;
bitmapImage.SetSourceAsync(memoryStream.AsRandomAccessStream());
}
}
if (value is string)
{
using (FileStream file = new FileStream((string)value, FileMode.Open))
{
IRandomAccessStream fileStream = file.AsRandomAccessStream();
bitmapImage.SetSource(fileStream);
fileStream.Dispose();
}
}
return bitmapImage;
}
public object ConvertBack(object value, Type targetType, object parameter, string culture)
{
throw new NotImplementedException();
}
}
And use it like:
<Page.Resources>
<converters:ImageToBitmapImageConverter x:Key="ImageToBitmapImageConverter" />
</Page.Resources>
<Image Source="{Binding CroppedImagePath, Mode=OneWay, Converter={StaticResource ImageToBitmapImageConverter}}"/ >
Upvotes: 0