在 DataContext 中使用时无法删除文件文件、DataContext

2023-09-07 14:43:21 作者:灬永杬菂神奇寳寳

我的应用程序在屏幕上显示图像(图像基于本地计算机上的文件),用户可以根据需要删除它们.

My application shows images on screen (images based upon files on the local computer) and users can delete them if needed.

每次我尝试删除文件时都会出现以下错误消息:

Every time I try to delete a file it results in the following error message:

"The process cannot access the file 'C:\Users\Dave\Desktop\Duplicate\Swim.JPG' because it is being used by another process."

我理解错误信息.

我有一个UserControl,它接受一个文件路径(通过构造函数中的参数),然后将它绑定到它的(UserControl)DataContext.

I have a UserControl which accepts a file path (via a parameter in the constructor) and then binds it to it's (UserControl) DataContext.

作为调试此问题的一部分,我发现问题是由于在 UserControl 中设置 DataContext.如果我从我的 UserControl 中删除 this.DataContext = this; 那么我可以删除该文件.

As part of debugging this issue I have found the issue is due to setting the DataContext within the UserControl. If I remove this.DataContext = this; from within my UserControl then I can delete the file.

所以,我的 TestUnit 看起来像

So, my TestUnit looks like

        Ui.UserControls.ImageControl ic = new ImageControl(
           @"C:UsersDaveDesktopDuplicateSwim.JPG");

        try
        {
            File.Delete(@"C:UsersDaveDesktopDuplicateSwim.JPG");
        }
        catch (Exception ex)
        {
            Assert.Fail(ex.Message);
        }

用户控制代码隐藏

    public ImageControl(string path)
    {
        this.FilePath = path;
        this.DataContext = this; // removing this line allows me to delete the file!
        InitializeComponent();
    }

    #region Properties

    private string _filePath;
    public string FilePath
    {
        get { return _filePath; }
        set
        {
            _filePath = value;
            OnPropertyChanged("FilePath");
        }
    }

如果重要的话,我的 UserControl XAML 正在使用绑定到FilePath"的Image"控件

If it matters, my UserControl XAML is using the 'Image' control, bound to 'FilePath'

我尝试在删除之前将 UserControl 设为 null,但这没有帮助.

I have tried making the UserControl null before deleting, this did not help.

我尝试将 IDisposible 接口添加到我的 UserControl 并在 Dispose() 方法设置中添加 this.DataContext = null; 但这没有帮助.

I have tried adding the IDisposible Interface to my UserControl and within the Dispose() method setting this.DataContext = null; but this did not help.

我做错了什么?我怎样才能删除这个文件(或者更准确地说,让它不被使用).

What am I doing wrong? How can I delete this file (or more accurately, make it unused).

推荐答案

问题不在于 DataContext,而在于 WPF 从文件中加载图像的方式.

The problem is not the DataContext, but simply the way WPF loads images from files.

当您将 Image 控件的 Source 属性绑定到包含文件路径的字符串时,WPF 会在内部从路径中创建一个新的 BitmapFrame 对象,基本上如下所示:

When you bind the Source property of an Image control to a string that contains a file path, WPF internally creates a new BitmapFrame object from the path basically like this:

string path = ...
var bitmapImage = BitmapFrame.Create(new Uri(path));

不幸的是,这会保留 WPF 打开的图像文件,因此您无法删除它.

Unfortunately this keeps the Image file opened by WPF, so that you can't delete it.

要解决这个问题,您必须将图像属性的类型更改为 ImageSource(或派生类型)并手动加载图像,如下所示.

To get around this you have to change the type of your image property to ImageSource (or a derived type) and load the image manually like shown below.

public ImageSource ImageSource { get; set; } // omitted OnPropertyChanged for brevity

private ImageSource LoadImage(string path)
{
    var bitmapImage = new BitmapImage();

    using (var stream = new FileStream(path, FileMode.Open))
    {
        bitmapImage.BeginInit();
        bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
        bitmapImage.StreamSource = stream;
        bitmapImage.EndInit();
        bitmapImage.Freeze(); // optional
    }

    return bitmapImage;
}

...
ImageSource = LoadImage(@"C:UsersDaveDesktopDuplicateSwim.JPG");