Подтвердить что ты не робот

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

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

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

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

"Свойство 'UriSource' или свойство 'StreamSource' должны быть установлены."

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

4b9b3361

Ответ 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");