Image UriSource и привязка данных

Я пытаюсь привязать список пользовательских объектов к изображению WPF следующим образом:

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

Но это не работает. Это ошибка, которую я получаю:

«Должно быть установлено свойство« UriSource »или свойство« StreamSource »."

Что мне не хватает?

21.08.2008 17:21:01
6 ОТВЕТОВ
РЕШЕНИЕ

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}}"/>
83
9.11.2017 10:02:00
(На самом деле преобразователь типа не создает BitmapImage, но другой подкласс ImageSource:, BitmapFrameDecodeкоторый является внутренним.)
H.B. 27.09.2011 04:44:50
@HB Как бы вы обратились обратно, если хотите сохранить изменение изображения?
Igor 16.06.2014 09:09:25
Альтернатива конвертеру: Сделайте свою собственность, которую вы привязываете (здесь:) ImageSourceтипа Uriили BitmapImageи разыгрываете там. Если вам нужно разобраться с возможными nullзначениями (сбой приведения и т. Д.), Добавьте TargetNullValue={x:Null}к своей привязке.
Gerrit 28.10.2015 12:10:31
Работал отлично! Ты
Mohammed A. Fadil 21.10.2019 06:59:45

У вас должна быть реализация интерфейса 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>
8
21.08.2008 17:35:54

Вы также можете просто установить атрибут 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;
    }
}

Я полагаю, что это может быть немного больше работы, чем преобразователь значения, но это еще один вариант.

18
21.08.2008 17:54:38
Подобная реализация идеально подходит для случаев, когда ваш растровый ресурс уже загружен в ваш объект, и вы хотите передать биты в привязку. СПАСИБО!
Scott Fletcher 17.10.2008 18:17:23

В этой статье Atul Gupta приведен пример кода, который охватывает несколько сценариев:

  1. Обычная привязка образа ресурса к свойству Source в XAML
  2. Обязательное изображение ресурса, но из кода позади
  3. Связывание изображения ресурса в коде с помощью Application.GetResourceStream
  4. Загрузка изображения из пути к файлу через поток памяти (то же самое применимо при загрузке данных изображения блога из базы данных)
  5. Загрузка изображения из пути к файлу, но с помощью привязки к пути к файлу
  6. Привязка данных изображения к пользовательскому элементу управления, который внутренне имеет элемент управления изображением через свойство зависимости
  7. То же, что в пункте 5, но также гарантирует, что файл не будет заблокирован на жестком диске
20
14.05.2009 10:18:33

Проблема с ответом, который был выбран здесь, заключается в том, что при переходе назад и вперед конвертер будет срабатывать при каждом показе страницы.

Это приводит к постоянному созданию новых файловых дескрипторов и блокирует любые попытки удаления файла, поскольку он все еще используется. Это можно проверить с помощью Process Explorer.

Если файл изображения может быть удален в какой-то момент, можно использовать такой конвертер: использование XAML для привязки к System.Drawing.Image в элемент управления System.Windows.Image

Недостаток этого метода потока памяти заключается в том, что изображения (изображения) загружаются и декодируются каждый раз, и кеширование не может быть выполнено: «Чтобы предотвратить декодирование изображений более одного раза, присвойте свойство Image.Source из Uri, а не используйте Потоки памяти "Источник:" Советы по производительности для приложений Магазина Windows, использующих XAML "

Чтобы решить проблему с производительностью, можно использовать шаблон хранилища для обеспечения уровня кэширования. Кэширование может происходить в памяти, что может вызвать проблемы с памятью, или в виде файлов миниатюр, которые находятся во временной папке, которая может быть очищена при выходе из приложения.

7
23.05.2017 12:26:19

вы можете использовать

Класс ImageSourceConverter

чтобы получить то, что вы хотите

    img1.Source = (ImageSource)new ImageSourceConverter().ConvertFromString("/Assets/check.png");
4
20.10.2013 18:00:02