Как освободить / кэшировать ресурсы изображений после получения их с помощью XAML - PullRequest
0 голосов
/ 02 октября 2018

В настоящее время я работаю в проекте WPF, использующем Prism 6, избегая, насколько это возможно, кода позади.У меня есть переменная в ViewModel, которая содержит локальный путь, где хранится изображение, о котором идет речь.В представлении я связываю свойство источника элемента управления Image с переменной ViewModel и могу отображать изображение.

Проблема возникает, когда мне нужно удалить изображение с диска, когда оно все еще отображается в представлении.Затем, если я это сделаю, я получу типичное «Изображение используется».Я читал на форуме о кешировании изображений, и мне интересно, смогу ли я применить его в этом случае, чтобы избежать такого поведения только при использовании XAML, если это возможно.

Я использую этот подход:

<Border Grid.Column="0" BorderThickness="2" BorderBrush="#808080" Height="300" 
        Width="300" Background="#FCFCFC">
    <Image Height="350" Width="350" HorizontalAlignment="Center" 
           VerticalAlignment="Center" Source="{Binding ImageUri}"/>
</Border>

Ответы [ 4 ]

0 голосов
/ 02 октября 2018

Вы можете написать конвертер для этого, чтобы преобразовать имя файла в байты

public class FilenameToBytesConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null)
        {
            return null;
        }
        var path = (string)value;

        if (!File.Exists(path))
        {
            return null;
        }

        return File.ReadAllBytes(path);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

и использовать его в представлении

<Window ...
        xmlns:Converters="clr-namespace:YourNamespacePath.Converters"/>

    <Window.Resources>
        <Converters:FilenameToBytesConverter x:Key="FilenameToBytesConverter"/>
    </Window.Resources>

    <Image Source="{Binding ImageUri, Converter={StaticResource FilenameToBytesConverter}}"/>
0 голосов
/ 02 октября 2018

Если вы можете назначить DataContext перед вызовом InitializeComponent (из MainWindow или UserControl), вы можете явно создать BitmapImage в XAML и установить его CacheOption в OnLoad.Фреймворк сразу же загрузит файл и не будет держать его открытым.

<Image>
    <Image.Source>
        <BitmapImage UriSource="{Binding ImageUri}" CacheOption="OnLoad"/>
    </Image.Source>
</Image>

В случае, если свойство DataContext или ImageUri должно быть установлено после InitializeComponent, вы можете добавить свойство типа ImageSource

public ImageSource Image
{
    get { return BitmapFrame.Create(
              ImageUri, BitmapCreateOptions.None, BitmapCacheOption.OnLoad); }
}

или byte[]:

public byte[] Image
{
    get { return File.ReadAllBytes(ImageUri.LocalPath); }
}

и привязать к нему, как:

<Image Source="{Binding Image}"/>

или асинхронно, чтобы увеличить скорость отклика пользовательского интерфейса:

<Image Source="{Binding Image, IsAsync=True}"/>
0 голосов
/ 02 октября 2018

Вам не нужно создавать ImageSource объект в вашем ViewModel.Вместо этого просто создайте свойство типа byte[], которое вы устанавливаете из файла, используя стандартные функции ввода-вывода.Затем вы можете связать свойство Source вашего Image элемента управления с этим байтовым массивом - элемент управления автоматически обработает преобразование в отображаемое изображение.

См. Мой ответ на этот вопрос for означает обрабатывать это асинхронно.

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

0 голосов
/ 02 октября 2018

Пока у вас есть ImageSource, указывающий на файл на локальном диске - вы не можете его удалить.Следующие 2 подхода приходят мне на ум:

  1. Поскольку у вас есть путь к реальному изображению - почему бы не скопировать его в папку TEMP и связать с этим путем.Таким образом, вы никогда не обращаетесь к реальному изображению, которое теперь можно удалить.

  2. Использование / сборка http-хоста (CMS) для файлов изображений (например) imgur (который также использует StackOverflow).Всегда сохраняйте / размещайте файлы на этом.Таким образом, ImagesSource является http uri.

...