2010-08-06 3 views
12

ListView를 개체 목록에 바인딩합니다.XAML을 사용하여 System.Drawing.Image를 System.Windows.Image 컨트롤에 바인딩

<ListView 
    ItemsSource="{ Binding Path=. }" 
    ItemTemplate="{DynamicResource EventTemplate}"> 

두 속성을 선언하는 개체에 바인딩됩니다.

string DisplayName { get; } 
System.Drawing.Image Image { get; set; } 

나는 DataTemplate을 채우려하지만 난 방법을 알아낼 수 없습니다; 내 템플리트에서 이렇게하면

<StackPanel Orientation="Horizontal"> 
    <Image Source="{ Binding Path=Image }" /> 
    <TextBlock Text="{ Binding Path=DisplayName }" /> 
</StackPanel>  

텍스트는 표시되지만 이미지는 표시되지 않습니다. 내가 도대체 ​​뭘 잘못하고있는 겁니까? 디버그 출력에

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

답변

34

나는 행복하게 발견했습니다. Reed Copsey's pointerthis tutorial을 사용하여 코드를 IValueConverter으로 감쌌습니다.

여기는 System.Drawing.Image부터 System.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; 
     } 
    } 
} 

그런 다음 이미지 변환기를 리소스로 XAML에 가져와야합니다.

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

<ListView.Resources> 
    <med:ImageConverter x:Key="imageConverter" /> 
</ListView.Resources> 

그런 다음 XAML에서이 변환기를 사용하여 새 변환기를 사용하여 이미지에 직접 바인딩 할 수 있습니다.

<Image Source="{ Binding Path=Image, Converter={StaticResource imageConverter} }" /> 
+1

메모리 사용량에 대한 질문이 있습니다.이 변환은 한 번만 또는 이미지가 표시되는 부분, 즉 ListBox에 표시 될 때마다 발생합니까 ?? – emesx

+1

정말 말할 수 없다 - WPF가 필요할 때마다 변환이 이루어 지므로 내부 구현 세부 사항이라고 생각합니다. 나는 그것이 반복해서 반복 될 이유가 없다고 생각하지만, 카운터에 집착하고 볼 가치가있을 것입니다. –

+1

'memoryStream'은 절대로 닫히지 않거나 폐기 될 수 없습니까? 나는 아주 비슷한 코드를 가지고있다. 심지어이 질문에서 나온 것일 수도 있지만, 그것은 더 추운 것이다. – Maslow

4

을 직접 바인딩 할 수 없습니다. GDI 이미지에서 WPF 이미지로 변환 할 수있는 변환기가 있어야합니다.

여기에 one approach입니다. 메모리 스트림을 사용하여 GDI 이미지에서 데이터를 가져 와서 BitmapSource 개체를 만듭니다.

+0

안녕하세요. 포인터입니다. 지금은 "Windows Forms에서 MVVM이 포함 된 WPF 로의 더 나은 사용자 및 개발자 경험"기사를 읽는 중반부입니다. 좋은 물건. 어쨌든, 그것은 저에게 답을 얻기에 충분한 것을주었습니다. 나는 그것을 나란히 게시했다. –

+0

@ 스티브 : 당신이 시리즈를 좋아한다는 소식을 듣고 기쁩니다;) –

+0

정말 도움이되었습니다. WPF 모델은 Windows 양식과 매우 다르며 필자의 수필은 내 두뇌에서 그것을 열어줍니다. –

관련 문제