【问题标题】:WPF In-Memory Image DisplayWPF 内存图像显示
【发布时间】:2010-06-10 19:59:44
【问题描述】:

我正在尝试为我的列表视图构建一个项目模板,并且我绑定到一个实体列表。我拥有的实体有一个我想显示的System.Drawing.Image,但到目前为止,我无法弄清楚如何将它绑定到<Image> 块。

我可以在互联网上找到的每个示例和文档都与可通过uri 访问的图像有关,即硬盘上或网站上的文件

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

【问题讨论】:

标签: .net wpf image data-binding


【解决方案1】:

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 方法快得多,因为它从不将位图数据序列化为流。

【讨论】:

    【解决方案2】:

    Ray Burns 的回答导致内存泄漏,因为

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

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

    GetHbitmap (Microsoft 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);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-08
      • 2014-02-21
      • 2011-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-07
      • 2018-01-27
      相关资源
      最近更新 更多