I've made a ListBox with items that have an image bound to them (Binding BitmapSource, UpdateSourceTrigger=PropertyChanged). They updated at runtime and all was fine but their background was black and not Transparent as i wished for.
Now i want to have the same functionality with PNG. So now I did bind to the URI of the PNG and tried to change the image and notify afterwards, but i get an error (probably because i want to save an image while its already open?)
I'll try my best to show all the relevant code: XAML:
<Image Source="{Binding Path=OutfitImageString, UpdateSourceTrigger=PropertyChanged}"/>
C# URI string, I wanted to use this to tell when the PNG was changed:
private string _OutfitImageString;
public string OutfitImageString
{
get { return _OutfitImageString; }
set
{
_OutfitImageString = value;
NotifyPropertyChanged("OutfitImageString");
}
}
And every time I change the Bitmap picture (its bound to an instance of a class) I run this method:
public void UpdateImage()
{
// new bitmap (transparent background by default)
Bitmap nb = new Bitmap(100, 110, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
// [ ... ] Create the Bitmap
// save to PNG to get a transparent background, every Person has a unique name
string saveAt = Directory.GetCurrentDirectory() + Name + "_outfit.png";
nb.Save(saveAt, System.Drawing.Imaging.ImageFormat.Png);
// notify that we changed the image (even tho the URI string is the same)
OutfitImageString = saveAt;
}
This line creates an Error, as soon as it is run for a 2. time:
nb.Save(saveAt, System.Drawing.Imaging.ImageFormat.Png);
Exception type -2147467259 Allgemeiner Fehler in GDI+. overflow excpetion: System.Runtime.InteropServices.ExternalException (0x80004005): Allgemeiner Fehler in GDI+. bei System.Drawing.Image.Save(String filename, ImageCodecInfo encoder, EncoderParameters encoderParams) bei System.Drawing.Image.Save(String filename, ImageFormat format)
I stored the BitmapSource of the Bitmap before and Bound to that aswell, this used to work perfectly (just the background was not transparent).
Also since these images are kind of temporary, I don't like saving them all the time :/
Thanks for the help, I am sorry the description is kinda messy... Just write if you need further details!
It is not at all necessary to save a bitmap file.
Change the type of your property from string to ImageSource
private ImageSource _OutfitImage;
public ImageSource OutfitImage
{
get { return _OutfitImage; }
set
{
_OutfitImage = value;
NotifyPropertyChanged(nameof(OutfitImage));
}
}
and bind to it like shown below (where setting UpdateSourceTrigger=PropertyChange
is pointless).
<Image Source="{Binding Path=OutfitImage}"/>
Then assign a value like this:
OutfitImage = BitmapToBitmapSource(nb);
...
public static BitmapSource BitmapToBitmapSource(System.Drawing.Bitmap bitmap)
{
var bitmapImage = new BitmapImage();
using (var stream = new MemoryStream())
{
bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
stream.Position = 0;
bitmapImage.BeginInit();
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.StreamSource = stream;
bitmapImage.EndInit();
}
return bitmapImage;
}