在很久以前就遇到这个问题,当时解决了,这过了几年,又遇到这个问题,这里做个总结,防止下次再踩坑了,也顺便帮助一下同样遇到这个问题的朋友 。
出现这个问题的原因是:将文件路径绑定到Image的Source上。
Image的Source属性实际上需要的是一个ImageSource类型,但是可以直接将string(文件路径)绑定到Source上。我查了一下WPF的源码,并没有找到是如何在绑定时将string转换成ImageSource。不过原理应该还是下面这样,所以会导致图片文件占用。
Image image = new Image(); image.BeginInit(); image.UriSource = new Uri(xxx); image.EndInit();
下面看一下文件占用的情况:
如下:
MainWindow.xaml
1 <Grid> 2 <Image Source="{Binding ImagePath}"/> 3 </Grid>
MainWindow.xaml.cs
1 public partial class MainWindow : Window 2 { 3 public MainWindow() 4 { 5 InitializeComponent(); 6 7 var viewModel = new MainWindowViewModel(); 8 this.DataContext = viewModel; 9 10 //假设D盘下有个d.jpeg文件 11 viewModel.ImagePath = @"D:\\d.jpeg"; 12 } 13 }
MainWindowViewModel.cs
1 public class MainWindowViewModel : INotifyPropertyChanged 2 { 3 private string imagePath; 4 5 public string ImagePath 6 { 7 get => imagePath; 8 set 9 { 10 imagePath = value; 11 RaiseChanged("ImagePath"); 12 } 13 } 14 15 public event PropertyChangedEventHandler PropertyChanged; 16 17 public void RaiseChanged(string propertyName) 18 { 19 PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 20 } 21 }
运行后可以看到D盘下的d.jpeg文件是不能删除的
解除文件占用的原理是在初始化时,就将图片加载到内存中,如下:
1 image.BeginInit(); 2 image.CacheOption = BitmapCacheOption.OnLoad; 3 image.CreateOptions = BitmapCreateOptions.IgnoreImageCache; 4 image.UriSource = new Uri(path, UriKind.Absolute); 5 image.EndInit();
了解原理后,我们就可以建立一个ImageSourceConvert来解除文件占用的问题
1 public class ImageSourceConverter : IValueConverter 2 { 3 public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 4 { 5 if (value == null) 6 return DependencyProperty.UnsetValue; 7 8 var path = value.ToString(); 9 BitmapImage image = new BitmapImage(); 10 image.BeginInit(); 11 image.CacheOption = BitmapCacheOption.OnLoad; 12 image.CreateOptions = BitmapCreateOptions.IgnoreImageCache; 13 image.UriSource = new Uri(path, UriKind.Absolute); 14 image.EndInit(); 15 return image; 16 } 17 18 public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 19 { 20 throw new NotImplementedException(); 21 } 22 }
MainWindow.xaml
1 <Window.Resources> 2 <local:ImageSourceConverter x:Key="ImageSourceConverter"/> 3 </Window.Resources> 4 <Grid> 5 <!--<Image Source="{Binding ImagePath}"/>--> 6 <Image Source="{Binding ImagePath,Converter={StaticResource ImageSourceConverter}}"/> 7 </Grid>