Я пытаюсь привязать список пользовательских объектов к изображению WPF следующим образом:
<Image>
<Image.Source>
<BitmapImage UriSource="{Binding Path=ImagePath}" />
</Image.Source>
</Image>
Но это не работает. Это ошибка, которую я получаю:
«Должно быть установлено свойство« UriSource »или свойство« StreamSource »."
Что мне не хватает?
WPF имеет встроенные конвертеры для определенных типов. Если вы привяжете Source
свойство Image к значению string
или Uri
, WPF будет использовать ImageSourceConverter для преобразования значения в значение ImageSource
.
Так
<Image Source="{Binding ImageSource}"/>
будет работать, если свойство ImageSource является строковым представлением действительного URI для изображения.
Конечно, вы можете свернуть свой собственный конвертер Binding:
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}}"/>
У вас должна быть реализация интерфейса 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>
Вы также можете просто установить атрибут 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;
}
}
Я полагаю, что это может быть немного больше работы, чем преобразователь значения, но это еще один вариант.
В этой статье Atul Gupta приведен пример кода, который охватывает несколько сценариев:
- Обычная привязка образа ресурса к свойству Source в XAML
- Обязательное изображение ресурса, но из кода позади
- Связывание изображения ресурса в коде с помощью Application.GetResourceStream
- Загрузка изображения из пути к файлу через поток памяти (то же самое применимо при загрузке данных изображения блога из базы данных)
- Загрузка изображения из пути к файлу, но с помощью привязки к пути к файлу
- Привязка данных изображения к пользовательскому элементу управления, который внутренне имеет элемент управления изображением через свойство зависимости
- То же, что в пункте 5, но также гарантирует, что файл не будет заблокирован на жестком диске
Проблема с ответом, который был выбран здесь, заключается в том, что при переходе назад и вперед конвертер будет срабатывать при каждом показе страницы.
Это приводит к постоянному созданию новых файловых дескрипторов и блокирует любые попытки удаления файла, поскольку он все еще используется. Это можно проверить с помощью Process Explorer.
Если файл изображения может быть удален в какой-то момент, можно использовать такой конвертер: использование XAML для привязки к System.Drawing.Image в элемент управления System.Windows.Image
Недостаток этого метода потока памяти заключается в том, что изображения (изображения) загружаются и декодируются каждый раз, и кеширование не может быть выполнено: «Чтобы предотвратить декодирование изображений более одного раза, присвойте свойство Image.Source из Uri, а не используйте Потоки памяти "Источник:" Советы по производительности для приложений Магазина Windows, использующих XAML "
Чтобы решить проблему с производительностью, можно использовать шаблон хранилища для обеспечения уровня кэширования. Кэширование может происходить в памяти, что может вызвать проблемы с памятью, или в виде файлов миниатюр, которые находятся во временной папке, которая может быть очищена при выходе из приложения.
вы можете использовать
Класс ImageSourceConverter
чтобы получить то, что вы хотите
img1.Source = (ImageSource)new ImageSourceConverter().ConvertFromString("/Assets/check.png");
BitmapImage
, но другой подклассImageSource
:,BitmapFrameDecode
который является внутренним.)ImageSource
типаUri
илиBitmapImage
и разыгрываете там. Если вам нужно разобраться с возможнымиnull
значениями (сбой приведения и т. Д.), ДобавьтеTargetNullValue={x:Null}
к своей привязке.