图像 UriSource 和数据绑定
-
09-06-2019 - |
题
我正在尝试将自定义对象列表绑定到 WPF 图像,如下所示:
<Image>
<Image.Source>
<BitmapImage UriSource="{Binding Path=ImagePath}" />
</Image.Source>
</Image>
但这不起作用。这是我收到的错误:
“必须设置属性‘UriSource’或属性‘StreamSource’。”
我缺少什么?
解决方案
WPF 具有针对某些类型的内置转换器。如果您绑定图像的 Source
财产给一个 string
或者 Uri
值,在底层 WPF 将使用 图像源转换器 将值转换为 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}}"/>
其他提示
本文 Atul Gupta 提供的示例代码涵盖了多种场景:
- 常规资源图像绑定到 XAML 中的 Source 属性
- 绑定资源图像,但来自代码隐藏
- 使用Application.GetResourceStream在代码隐藏中绑定资源图像
- 通过内存流从文件路径加载图像(从数据库加载博客图像数据时同样适用)
- 从文件路径加载图像,但使用绑定到文件路径属性
- 通过依赖属性将图像数据绑定到内部具有图像控件的用户控件
- 与第 5 点相同,但还要确保文件不会被锁定在硬盘上
您还可以简单地设置 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;
}
}
我想这可能比值转换器多一点工作,但它是另一种选择。
你需要有一个实施 值转换器 将 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>
这里选择的答案的问题是,来回导航时,每次显示页面时都会触发转换器。
这会导致不断创建新的文件句柄,并且会阻止任何删除该文件的尝试,因为该文件仍在使用中。这可以通过使用 Process Explorer 进行验证。
如果图像文件可能在某个时候被删除,则可以使用如下转换器:使用 XAML 将 System.Drawing.Image 绑定到 System.Windows.Image 控件中
这种内存流方法的缺点是每次都会加载和解码图像并且无法进行缓存:“要防止图像被解码不止一次,请从URI分配image.source属性,而不是使用内存流”来源:“使用 XAML 的 Windows 应用商店应用程序的性能提示”
为了解决性能问题,可以使用存储库模式来提供缓存层。缓存可能发生在内存中,这可能会导致内存问题,或者作为缩略图文件驻留在临时文件夹中,在应用程序退出时可以将其清除。
你可以使用
图像源转换器类
得到你想要的
img1.Source = (ImageSource)new ImageSourceConverter().ConvertFromString("/Assets/check.png");