使用XAML将System.Drawing.Image绑定到System.Windows.Image控件

Ste*_*per 12 c# wpf xaml binding image

我正在将ListView绑定到对象列表,就像这样;

<ListView 
    ItemsSource="{ Binding Path=. }"
    ItemTemplate="{DynamicResource EventTemplate}">   
Run Code Online (Sandbox Code Playgroud)

我绑定了一个声明两个属性的对象;

string DisplayName { get; }
System.Drawing.Image Image { get; set; }
Run Code Online (Sandbox Code Playgroud)

我想填充一个,DataTemplate但我无法弄清楚如何; 如果我在模板中这样做;

<StackPanel Orientation="Horizontal">
    <Image Source="{ Binding Path=Image }" />
    <TextBlock Text="{ Binding Path=DisplayName }" />
</StackPanel>      
Run Code Online (Sandbox Code Playgroud)

文本出现但图像没有.我究竟做错了什么?调试输出显示

System.Windows.Data Error: 1 : Cannot create default converter
to perform 'one-way' conversions between types
'System.Drawing.Image' and 'System.Windows.Media.ImageSource'.
Consider using Converter property of Binding.
BindingExpression:Path=Image; DataItem='RealElement'
(HashCode=54308798); target element is 'Image' (Name='');
target property is 'Source' (type 'ImageSource')
Run Code Online (Sandbox Code Playgroud)

Ste*_*per 35

找到了一种我很满意的方式.使用Reed Copsey的指针本教程,我将代码包装为IValueConverter.

下面是从转炉System.Drawing.ImageSystem.Windows.Media.ImageSource;

using System;
using System.Drawing.Imaging;
using System.Globalization;
using System.IO;
using System.Windows.Data;

namespace System.Windows.Media
{
    /// <summary>
    /// One-way converter from System.Drawing.Image to System.Windows.Media.ImageSource
    /// </summary>
    [ValueConversion(typeof(System.Drawing.Image), typeof(System.Windows.Media.ImageSource))]
    public class ImageConverter : IValueConverter
    {
        public object Convert(object value, Type targetType,
            object parameter, CultureInfo culture)
        {
            // empty images are empty...
            if (value == null) { return null; }

            var image = (System.Drawing.Image)value;
            // Winforms Image we want to get the WPF Image from...
            var bitmap = new System.Windows.Media.Imaging.BitmapImage();
            bitmap.BeginInit();
            MemoryStream memoryStream = new MemoryStream();
            // Save to a memory stream...
            image.Save(memoryStream, ImageFormat.Bmp);
            // Rewind the stream...
            memoryStream.Seek(0, System.IO.SeekOrigin.Begin);
            bitmap.StreamSource = memoryStream;
            bitmap.EndInit();
            return bitmap;
        }

        public object ConvertBack(object value, Type targetType,
            object parameter, CultureInfo culture)
        {
            return null;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,您需要将图像转换器作为资源引入XAML;

xmlns:med="clr-namespace:System.Windows.Media"
...

<ListView.Resources>
    <med:ImageConverter x:Key="imageConverter" />
</ListView.Resources>
Run Code Online (Sandbox Code Playgroud)

然后你可以在XAML中使用它直接绑定到Image,使用新的转换器;

<Image Source="{ Binding Path=Image, Converter={StaticResource imageConverter} }" />
Run Code Online (Sandbox Code Playgroud)

  • `memoryStream`永远不会被关闭或处理掉,这是一个值得关注的问题吗?我有一些非常相似的代码,甚至可能来自这个问题,但它更加丑陋. (2认同)
  • 对于未来的读者,请记住在属性设置器中处理之前的“Image”实例。这是对@Maslow 评论的回应。 (2认同)

Ree*_*sey 5

你不能直接绑定它 - 你需要有某种类型的转换器来从 GDI 图像转换为 WPF 图像。

这是一种方法- 它使用内存流从 GDI 图像中提取数据并创建一个 BitmapSource 对象。