WPF как очистить Source у Image Control

465
28 октября 2017, 14:19

Мне нужно загружать картинку из бд и отображать ее на екране в контроле Image, после чего в определенном моменте мне нужно очищать Source тоесть путь к картинке что бы ее удалить и загрузить новую.

Свойство прибинденное к Source у Image:

private string photo;
public string Photo
{
   get { return photo; }
   set
   {
       photo = value;
       OnPropertyChanged("Photo");
   }
}

Очищаю путь к картинке и загружаю новую из бд:

// пытаюсь заставить сбросить путь
Photo = null;
// при попытке удаление вылазит ошибка "невозможно удалить так как используеться другим процесом"
File.Delete(Environment.CurrentDirectory + "\\Photo.png");
// загрузка картинки з бд на форму
if (SelectedVerstatOperator.Photo != null)
{
    ImageLoadFromDataBase(SelectedVerstatOperator.Photo);
}

Метод ImageLoadFromDataBase:

private void ImageLoadFromDataBase(byte[] image)
{
    using (var ms = new MemoryStream(image))
    {
        // создаю новую картинку
        var photo = System.Drawing.Image.FromStream(ms);
        // сохраняю ее на диск
        photo.Save(Environment.CurrentDirectory + "\\Photo.png");
        // задаю путь к картинке для отображения в Image
        Photo = Environment.CurrentDirectory + "\\Photo.png";
    }
}

Как заставить Image оставить в покое картинку? Что бы я ее удалил

Answer 1

Нюанс в том, что XAML кэширует все изображения, не спрашивая на это разрешения. Чтобы избавиться от блокировки файла, нужно создать BitmapImage с CacheOption равным BitmapCacheOption.OnLoad. Сделать это можно либо напрямую в коде, и тогда забиндиться уже не на string, а на BitmapImage, либо с помощью конвертера.

Вот конвертер, написанный Kent Boogaart:

/// <summary>
/// This converter facilitates a couple of requirements around images. Firstly, it automatically disposes of image streams as soon as images
/// are loaded, thus avoiding file access exceptions when attempting to delete images. Secondly, it allows images to be decoded to specific
/// widths and / or heights, thus allowing memory to be saved where images will be scaled down from their original size.
/// </summary>
public sealed class BitmapFrameConverter : IValueConverter
{
    //doubles purely to facilitate easy data binding
    private double _decodePixelWidth;
    private double _decodePixelHeight;
    public double DecodePixelWidth
    {
        get
        {
            return _decodePixelWidth;
        }
        set
        {
            _decodePixelWidth = value;
        }
    }
    public double DecodePixelHeight
    {
        get
        {
            return _decodePixelHeight;
        }
        set
        {
            _decodePixelHeight = value;
        }
    }
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        string path = value as string;
        if (path != null)
        {
            //create new stream and create bitmap frame
            BitmapImage bitmapImage = new BitmapImage();
            bitmapImage.BeginInit();
            bitmapImage.StreamSource = new FileStream(path, FileMode.Open, FileAccess.Read);
            bitmapImage.DecodePixelWidth = (int) _decodePixelWidth;
            bitmapImage.DecodePixelHeight = (int) _decodePixelHeight;
            //load the image now so we can immediately dispose of the stream
            bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
            bitmapImage.EndInit();
            //clean up the stream to avoid file access exceptions when attempting to delete images
            bitmapImage.StreamSource.Dispose();
            return bitmapImage;
        }
        else
        {
            return DependencyProperty.UnsetValue;
        }
    }
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return DependencyProperty.UnsetValue;
    }
}

См. Delete image file used by XAML.

Answer 2

Решил так. Сохраняю картинку с рандомным именем в папку Temp

private void LoadImageFromDataBase(byte[] image)
    {
        using (var ms = new MemoryStream(image))
        {
            var photo = System.Drawing.Image.FromStream(ms);
            string randomFileName = Path.GetRandomFileName();
            randomFileName = randomFileName.Replace(".", "");
            var path = Environment.CurrentDirectory + "\\Temp\\" + randomFileName + ".png";
            photo.Save(path);
            Photo = path;
        }
    }

А при закрыти программы удаляю папку Temp и заново создаю ее

string dir = System.Environment.CurrentDirectory + "\\Temp";
System.IO.Directory.Delete(dir, true);
System.IO.Directory.CreateDirectory(dir);
READ ALSO
Wpf CefSharp медленная работа сайта

Wpf CefSharp медленная работа сайта

Загружаю сайт (html5 js css) локально, сайт грузится, но работает с тормозами, подскажите, в чем проблема?

258
Считается ли ошибкой использования Socket-ов для соединения веб-приложения MVC и клиентского десктопного приложения в проекте ASP.NET Core?

Считается ли ошибкой использования Socket-ов для соединения веб-приложения MVC и клиентского десктопного приложения в проекте ASP.NET Core?

Считается ли ошибкой использования Socket-ов для соединения веб-приложения MVC и клиентского десктопного приложения в проекте ASPNET Core?

273
Идиомы программирования на C# [требует правки]

Идиомы программирования на C# [требует правки]

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

306
Проверка на наличие в [,] массиве

Проверка на наличие в [,] массиве

Есть переменная, допустим string s = "/87536464", необходимо проверить её на наличие в первом столбце [,] массива и в случае, если такого значения там...

359