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