问题
Im trying to build an Item Template for my list-view and im bound to a list of Entities. The entity I have has a System.Drawing.Image
that I'd like to display, but so far I cannot for the life of me figure out how to bind it to the <Image>
block.
Every example and documentation I can find on the internet pertains to Images accessible via an uri
i.e. File on HDD or On Website
<DataTemplate x:Key="LogoPreviewItem">
<Border BorderBrush="Black" BorderThickness="1">
<DockPanel Width="150" Height="100">
<Image>
<Image.Source>
<!--
{Binding PreviewImage} is where the System.Drawing.Image
is in this context
-->
</Image.Source>
</Image>
<Label DockPanel.Dock="Bottom" Content="{Binding CustomerName}" />
</DockPanel>
</Border>
</DataTemplate>
回答1:
A System.Drawing.Image is a WinForms / GDI+ object and is really out of place in the WPF world. A pure WPF program will generally not use System.Drawing.Image but will use BitmapSource instead. However sometimes we are stuck with the old stuff for a while.
You can convert your image from the old technology into the new as follows:
var oldImage = ...; // System.Drawing.Image
var oldBitmap =
oldImage as System.Drawing.Bitmap ??
new System.Drawing.Bitmap(oldImage);
var bitmapSource =
System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
oldBitmap.GetHbitmap(System.Drawing.Color.Transparent),
IntPtr.Zero,
new Int32Rect(0, 0, oldBitmap.Width, oldBitmap.Height),
null);
Now you can set:
myImage.Source = bitmapSource;
This is much faster than the MemoryStream approach that you will find described elsewhere, since it never serializes the bitmap data to a stream.
回答2:
The answer by Ray Burns results in a memory leak since
oldBitmap.GetHbitmap(System.Drawing.Color.Transparent)
allocates memory which is never released.
As stated under "Remarks" in the documentation for GetHbitmap
(Microsoft Docs):
You are responsible for calling the GDI DeleteObject method to free the memory used by the GDI bitmap object.
Following the documentation, memory is freed by importing and using DeleteObject()
:
[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern bool DeleteObject(IntPtr hObject);
var hBitmap = someBitmap.GetHbitmap(...);
// Do something with hBitmap
DeleteObject(hBitmap);
The answer by Ray Burns should thus be modified to:
[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern bool DeleteObject(IntPtr hObject);
...
var oldImage = ...; // System.Drawing.Image
var oldBitmap =
oldImage as System.Drawing.Bitmap ??
new System.Drawing.Bitmap(oldImage);
var hOldBitmap = oldBitmap.GetHbitmap(System.Drawing.Color.Transparent);
var bitmapSource =
System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
hOldBitmap,
IntPtr.Zero,
new Int32Rect(0, 0, oldBitmap.Width, oldBitmap.Height),
null);
DeleteObject(hOldBitmap);
来源:https://stackoverflow.com/questions/3018004/wpf-in-memory-image-display