在很久以前就遇到这个问题,当时解决了,这过了几年,又遇到这个问题,这里做个总结,防止下次再踩坑了,也顺便帮助一下同样遇到这个问题的朋友 。
出现这个问题的原因是:将文件路径绑定到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>