Не удается удалить файл, используемый каким-либо другим процессом
Я показываю некоторое изображение в моем приложении wpf, используя следующий код:
<Image Source="{Binding Path=TemplateImagePath, Mode=TwoWay}" Grid.Row="3" Grid.Column="2" Width="400" Height="200"/>
И установка свойства привязки внутри конструктора code behind путем навигации по некоторому каталогу, ниже приведен код:
DirectoryInfo Dir = new DirectoryInfo(@"D:/Template");
if (Dir.Exists)
{
if (Dir.GetFiles().Count() > 0)
{
foreach (FileInfo item in Dir.GetFiles())
{
TemplateImagePath = item.FullName;
}
}
}
Но если пользователь загружает какое-то другое изображение, то мне нужно удалить это старое изображение, которое я делаю следующим образом и устанавливаю привязку изображения к нулю:
DirectoryInfo Dir = new DirectoryInfo(@"D:/Template");
if (Dir.Exists)
{
if (Dir.GetFiles().Count() > 0)
{
foreach (FileInfo item in Dir.GetFiles())
{
TemplateImagePath= null;
File.Delete(item.FullName);
}
}
}
Но я получаю исключение, которое не может удалить файл, используемый каким-либо другим процессом. Как я могу это сделать? удалить его?
2 ответа:
Чтобы иметь возможность удалить изображение, пока оно отображается в ImageControl, вы должны создать новый BitmapImage или BitmapFrame объект, который имеет BitmapCacheOption.OnLoad набор. Растровое изображение будет загружено из файла немедленно, и файл не будет заблокирован после этого.
Измените свое свойство с
string TemplateImagePath
наImageSource TemplateImage
и свяжите следующим образом:<Image Source="{Binding TemplateImage}"/>
Задайте свойство
TemplateImage
следующим образом:BitmapImage image = new BitmapImage(); image.BeginInit(); image.CacheOption = BitmapCacheOption.OnLoad; image.UriSource = new Uri(item.FullName); image.EndInit(); TemplateImage = image;
Или вот это:
TemplateImage = BitmapFrame.Create( new Uri(item.FullName), BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
Если вы хотите сохранить привязку к свойству
TemplateImagePath
вместо этого вы можете использовать Binding converter, который преобразует строку в ImageSource, как показано выше.
Согласно предложению Клеменса, вот связывающий конвертер, чтобы иметь хорошее повторное использование кода:
namespace Controls { [ValueConversion(typeof(String), typeof(ImageSource))] public class StringToImageSourceConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (!(value is string valueString)) { return null; } try { ImageSource image = BitmapFrame.Create(new Uri(valueString), BitmapCreateOptions.IgnoreImageCache, BitmapCacheOption.OnLoad); return image; } catch { return null; } } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } } }
И есть строка для привязки, например
public string MyImageString { get; set; } = @"C:\test.jpg"
А в UI используется конвертер, в моем случае из библиотеки с именем " Controls"
<Window x:Class="MainFrame" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:controls="clr-namespace:Controls;assembly=Controls"> <Window.Resources> <controls:StringToImageSourceConverter x:Key="StringToImageSourceConverter" /> </Window.Resources> <Grid> <Image Source="{Binding MyImageString, Converter={StaticResource StringToImageSourceConverter}}" /> </Grid> </Window>