WPF内存中图像显示

时间:2010-06-10 19:59:45

标签: .net wpf image data-binding

我试图为我的列表视图构建一个项目模板,并且我绑定到一个实体列表。我所拥有的实体有System.Drawing.Image我想展示,但到目前为止,我不能为我的生活弄清楚如何将它绑定到<Image>块。

我可以在互联网上找到的每个示例和文档都适用于可通过uri访问的图像,即HDD或网站上的文件

    <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>

2 个答案:

答案 0 :(得分:4)

System.Drawing.Image是一个WinForms / GDI +对象,在WPF世界中确实不合适。纯WPF程序通常不会使用System.Drawing.Image,而是使用BitmapSource。然而,有时我们会坚持旧的东西。

您可以将图像从旧技术转换为新技术,如下所示:

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);

现在你可以设置:

myImage.Source = bitmapSource;

这比您在其他地方描述的MemoryStream方法快得多,因为它从未将位图数据序列化为流。

答案 1 :(得分:0)

Ray Burns的答案自此以来导致内存泄漏

oldBitmap.GetHbitmap(System.Drawing.Color.Transparent)

分配永远不会释放的内存。

GetHbitmapMicrosoft Docs)文档中“备注”所述:

  

您负责调用GDI DeleteObject方法以释放GDI位图对象使用的内存。

按照说明文件,通过导入和使用DeleteObject()释放内存:

[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern bool DeleteObject(IntPtr hObject);

var hBitmap = someBitmap.GetHbitmap(...);

// Do something with hBitmap

DeleteObject(hBitmap);

因此,Ray Burns的答案应修改为:

[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);