【问题标题】:Image UriSource and Data Binding图像 UriSource 和数据绑定
【发布时间】:2010-09-06 10:36:36
【问题描述】:

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

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

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

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

我错过了什么?

【问题讨论】:

  • 不幸的是,答案中没有解释失败的实际原因。请参阅this无论出于何种原因,WPF/XAML 都不支持将 Uri 对象直接绑定到 BitmapImage 对象的 UriSource。运行时,应用程序会失败并出现错误,)跨度>

标签: .net wpf data-binding xaml


【解决方案1】:

WPF 具有用于某些类型的内置转换器。如果将 Image 的 Source 属性绑定到 stringUri 值,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}}"/>

【讨论】:

  • (实际上类型转换器并没有创建BitmapImage,而是ImageSource的另一个子类:BitmapFrameDecode,这是内部的。)
  • @H.B.如果您想保留图像的更改,您将如何转换回来?
  • 转换器的替代方案:使您的属性绑定到(此处:ImageSource)类型为UriBitmapImage 并在那里转换。如果您需要处理可能的 null 值(转换失败等),请将 TargetNullValue={x:Null} 添加到您的绑定中。
  • 完美运行! ty
  • 这如何解释错误消息“必须设置属性'UriSource'或属性'StreamSource'”? (使用 Uri 设置路径的 OP 代码有什么问题?)
【解决方案2】:

Atul Gupta 的This article 提供了涵盖多种场景的示例代码:

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

【讨论】:

    【解决方案3】:

    您也可以简单地设置 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;
        }
    }
    

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

    【讨论】:

    • 当您的位图资源已经加载到您的对象中并且您希望将位传递给绑定时,与此类似的实现是完美的。谢谢!
    【解决方案4】:

    您需要实现IValueConverter 接口,将uri 转换为图像。您的 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>
    

    【讨论】:

    • 看起来转换器返回了一个BitmapImage,结果应该直接赋值给Image.Source,而不是另一个BitmapImage UriSource
    【解决方案5】:

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

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

    如果图像文件可能在某个时候被删除,则可以使用如下转换器: using XAML to bind to a System.Drawing.Image into a System.Windows.Image control

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

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

    【讨论】:

      【解决方案6】:

      你可以使用

      ImageSourceConverter 类

      得到你想要的

          img1.Source = (ImageSource)new ImageSourceConverter().ConvertFromString("/Assets/check.png");
      

      【讨论】:

        猜你喜欢
        • 2011-12-26
        • 2011-03-10
        • 2015-06-26
        • 2021-11-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-15
        相关资源
        最近更新 更多