68

我正在尝试将自定义对象列表绑定到 WPF 图像,如下所示:

<Image>
    <Image.Source>
        <BitmapImage UriSource="{Binding Path=ImagePath}" />
    </Image.Source>
</Image>

但它不起作用。这是我得到的错误:

“必须设置属性 'UriSource' 或属性 'StreamSource'。”

我错过了什么?

4

6 回答 6

85

WPF 具有用于某些类型的内置转换器。如果将 Image 的Source属性绑定到 astringUri值,WPF 将使用ImageSourceConverter将值转换为ImageSource.

所以

<Image Source="{Binding ImageSource}"/>

如果 ImageSource 属性是图像的有效 URI 的字符串表示形式,它将起作用。

您当然可以滚动自己的绑定转换器:

public class ImageConverter : IValueConverter
{
    public object Convert(
        object value, Type targetType, object parameter, CultureInfo culture)
    {
        return new BitmapImage(new Uri(value.ToString()));
    }

    public object ConvertBack(
        object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

并像这样使用它:

<Image Source="{Binding ImageSource, Converter={StaticResource ImageConverter}}"/>
于 2008-08-21T18:38:50.580 回答
21

Atul Gupta 的这篇文章的示例代码涵盖了几种场景:

  1. 常规资源图像绑定到 XAML 中的 Source 属性
  2. 绑定资源图像,但来自后面的代码
  3. 使用 Application.GetResourceStream 在代码中绑定资源图像
  4. 通过内存流从文件路径加载图像(从数据库加载博客图像数据时同样适用)
  5. 从文件路径加载图像,但使用绑定到文件路径属性
  6. 通过依赖属性将图像数据绑定到内部具有图像控制的用户控件
  7. 与第 5 点相同,但还要确保文件不会被锁定在硬盘上
于 2009-05-14T10:18:33.920 回答
18

您也可以简单地设置 Source 属性而不是使用子元素。为此,您的类需要将图像作为位图图像返回。这是我完成的一种方式的示例

<Image Width="90" Height="90" 
       Source="{Binding Path=ImageSource}"
       Margin="0,0,0,5" />

而类属性就是这个

public object ImageSource {
    get {
        BitmapImage image = new BitmapImage();

        try {
            image.BeginInit();
            image.CacheOption = BitmapCacheOption.OnLoad;
            image.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
            image.UriSource = new Uri( FullPath, UriKind.Absolute );
            image.EndInit();
        }
        catch{
            return DependencyProperty.UnsetValue;
        }

        return image;
    }
}

我想它可能比值转换器多一点工作,但它是另一种选择。

于 2008-08-21T17:45:11.190 回答
8

您需要实现将 uri 转换为图像的IValueConverter接口。您的 IValueConverter 的 Convert 实现将如下所示:

BitmapImage image = new BitmapImage();
image.BeginInit();
image.UriSource = new Uri(value as string);
image.EndInit();

return image;

然后您将需要在绑定中使用转换器:

<Image>
    <Image.Source>
        <BitmapImage UriSource="{Binding Path=ImagePath, Converter=...}" />
    </Image.Source>
</Image>
于 2008-08-21T17:35:54.427 回答
8

此处选择的答案的问题是,在来回导航时,每次显示页面时都会触发转换器。

这会导致不断创建新的文件句柄,并将阻止任何删除该文件的尝试,因为它仍在使用中。这可以通过使用 Process Explorer 来验证。

如果图像文件可能在某个时候被删除,则可能会使用这样的转换器: 使用 XAML 将 System.Drawing.Image 绑定到 System.Windows.Image 控件

这种内存流方法的缺点是图像每次都被加载和解码,并且无法进行缓存:“为了防止图像被多次解码,请从 Uri 分配 Image.Source 属性,而不是使用内存流” 来源:“使用 XAML 的 Windows 应用商店应用的性能提示”

为了解决性能问题,可以使用存储库模式来提供缓存层。缓存可能发生在内存中,这可能会导致内存问题,或者作为驻留在临时文件夹中的缩略图文件,可以在应用程序退出时清除。

于 2012-12-15T19:36:03.383 回答
5

你可以使用

ImageSourceConverter 类

得到你想要的

    img1.Source = (ImageSource)new ImageSourceConverter().ConvertFromString("/Assets/check.png");
于 2013-10-20T18:00:02.000 回答