Wpf Image Control блокирует файл

У меня есть простое Window с кнопкой и второе Window открывается, когда я нажимаю Button . Во втором Window есть элемент управления Image , который отображает .png-файл. Поэтому, если я использую свойство FileObject для Binding все в порядке, я могу удалить файл из File Explorer . Но если я использую свойство FileName для Binding я не могу удалить файл из File Explorer , я получаю исключение ОС. Я не могу этого сделать, даже если я закрываю второе окно, даже если я вызываю GC явно. В чем проблема с свойством FileName ? Есть идеи?

Win 7, Net 4.0

Window1

  

Window2

    public partial class Window2 : Window { public Window2() { InitializeComponent(); DataContext = this; FileName = "D:/pdf/myfile.png"; Closing += Window2_Closing; } public String FileName { get; set; } public Object FileObject { get { if (String.IsNullOrEmpty(FileName)) return null; if (!File.Exists(FileName)) return null; var ms = new MemoryStream(); var bi = new BitmapImage(); using (var fs = new FileStream(FileName, FileMode.Open, FileAccess.Read)) { fs.CopyTo(ms); bi.BeginInit(); bi.StreamSource = ms; bi.EndInit(); } return bi; } } void Window2_Closing(Object sender, System.ComponentModel.CancelEventArgs e) { GC.Collect(); GC.WaitForPendingFinalizers(); } } 

Когда вы привязываете свойство Image.Source к Uri (или строке, из которой создается Uri внутри), WPF использует встроенный конвертер типов, который создает BitmapFrame из Uri.

Если Uri содержит путь к локальному файлу, BitmapFrame сохраняет файл открытым, если он существует. Это может быть больше, чем на самом деле используется в вашем приложении, поскольку оно может быть кэшировано WPF.

Когда вам нужно будет удалить файл, из которого было загружено изображение, вы всегда должны использовать свой подход к FileObject , но он должен выглядеть следующим образом:

 public ImageSource Image { get { ... var bi = new BitmapImage(); using (var fs = new FileStream(FileName, FileMode.Open, FileAccess.Read)) { bi.BeginInit(); bi.CacheOption = BitmapCacheOption.OnLoad; bi.StreamSource = fs; bi.EndInit(); } return bi; } } 

Или вот так:

 public ImageSource Image { get { using (var fs = new FileStream(FileName, FileMode.Open, FileAccess.Read)) { return BitmapFrame.Create( fs, BitmapCreateOptions.None, BitmapCacheOption.OnLoad); } } } 

Или вы привязываетесь к свойству FileName с помощью конвертера привязки, который создает BitmapImage или BitmapFrame, как показано выше.

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

 var image = new BitmapImage(); image.BeginInit(); image.CacheOption = BitmapCacheOption.OnLoad; image.CreateOptions = BitmapCreateOptions.IgnoreImageCache; image.UriSource = new Uri(FilePath); image.EndInit(); return image;