c# - Wpf 图像控件阻止文件

标签 c# wpf image

我有一个带有按钮的简单 Window,当我单击 Button 时会打开第二个 Window。第二个 Window 有一个 Image 控件,它显示一个 .png 文件。因此,如果我将 FileObject 属性用于 Binding 一切正常,我可以从 File Explorer 中删除文件。但是,如果我将 FileName 属性用于 Binding,我将无法从 File Explorer 中删除文件,我会遇到操作系统异常。即使我关闭第二个窗口,即使我显式调用 GC,我也不能这样做。 FileName 属性有什么问题?有任何想法吗?

Win 7、Net 4.0

窗口1

<Grid>
    <Button Content="Ok"
            Width="100" 
            VerticalAlignment="Center" 
            HorizontalAlignment="Center" 
            Click="Click" 
            Padding="0,2,0,2" 
            IsDefault="True" 
            Name="_btnOk"/>
</Grid> 



public partial class Window : Window
{

    public Window()
    {
        InitializeComponent();
        DataContext = this;
    }

    private void Click(Object sender, RoutedEventArgs e)
    {
        var window = new Window3();
        window.ShowDialog();
    }
}

窗口2

<Grid>
    <Image Source="{Binding FileObject}"></Image>
</Grid>

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 属性绑定(bind)到一个 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);
        }
    }
}

或者,您使用创建 BitmapImage 或 BitmapFrame 的绑定(bind)转换器绑定(bind)到 FileName 属性,如上所示。

关于c# - Wpf 图像控件阻止文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29625428/

相关文章:

wpf - 绑定(bind)属性中的“自动”值 'width'

c# - 从非托管代码加载混合模式程序集

javascript - 如何在 JavaScript 中向 ContextualWeb 图像搜索 API 发出 GET 请求?

c# - 是否可以在枚举中保存类型(使用 "typeof()")?

c# - 嵌套任务和子任务有什么区别

c# - 检查异步方法的调用 Received()

c# - IIS System.OutOfMemoryException 问题 Web 服务

c# - WPF RichTextBox 第一行\n 未打印

JavaFX - 加载图像和内存问题

android - 如何在 Android 上更改 ImageView 的图像