WPF图像控制块中的文件 [英] Wpf Image Control blocks the file

查看:135
本文介绍了WPF图像控制块中的文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的窗口使用按钮和第二窗口当我点击<$ C $打开C>按钮。第二个窗口有一个图片控件,它显示的.png文件。所以,如果我用文件对象属性绑定一切正常,我可以删除文件档案资源管理器。但是,如果使用文件名属性绑定我无法从删除文件文件浏览器,我得到的操作系统异常。如果我关闭第二个窗口,我不能这样做就算了,即使我调用 GC 明确。
什么是文件名属性的问题?有任何想法吗?

的Win 7,净4.0

窗口1

 &LT;网格和GT;
    &LT;按钮内容=确定
            WIDTH =100
            VerticalAlignment =中心
            的Horizo​​ntalAlignment =中心
            点击=点击
            填充=0,2,0,2
            ISDEFAULT =真
            NAME =_ btnOk/&GT;
&LT; /网格和GT;公共部分类窗口:窗口
{    公共窗口()
    {
        的InitializeComponent();
        的DataContext =这一点;
    }    私人无效点击(对象发件人,RoutedEventArgs E)
    {
        变种窗口=新Window3();
        window.ShowDialog();
    }
}

窗口2

 &LT;网格和GT;
    &lt;图像来源={结合的FileObject}&GT;&LT; /图像&GT;
&LT; /网格和GT;公共部分类窗口2:窗口
{
    公共窗口2()
    {
        的InitializeComponent();
        的DataContext =这一点;
        文件名=D:/pdf/myfile.png        关闭+ = Window2_Closing;
    }    公共字符串文件名{搞定;组; }    公共对象文件对象
    {
        得到
        {
            如果(String.IsNullOrEmpty(文件名))
                返回null;            如果(!File.Exists(文件名))
                返回null;            VAR毫秒=新的MemoryStream();
            VAR双向=新的BitmapImage();            使用(VAR FS =新的FileStream(文件名,FileMode.Open,FileAccess.Read))
            {
                fs.CopyTo(毫秒);
                bi.BeginInit();
                bi.StreamSource =毫秒;
                bi.EndInit();
            }
            返回双向;
        }
    }    无效Window2_Closing(对象发件人,System.ComponentModel.CancelEventArgs E)
    {
        所以GC.Collect();
        GC.WaitForPendingFinalizers();
    }
}


解决方案

在你的 Image.Source 属性绑定到的URI(或字符串,从中乌里在内部创建),使用WPF,创建一个内置式转换器 BitmapFrame 从URI。

如果URI包含本地文件的路径,则BitmapFrame保持文件打开,只要它存在。这可能比它在你的应用中实际使用,因为它可能会通过用WPF缓存。

当你需要能够删除的图像从加载的文件,你应该总是使用你的文件对象方法,但它应该是这样的:

 公共图像的ImageSource
{
    得到
    {
        ...
        VAR双向=新的BitmapImage();
        使用(VAR FS =新的FileStream(文件名,FileMode.Open,FileAccess.Read))
        {
            bi.BeginInit();
            bi.CacheOption = BitmapCacheOption.OnLoad;
            bi.StreamSource = FS;
            bi.EndInit();
        }
        返回双向;
    }
}

或者是这样的:

 公共图像的ImageSource
{
    得到
    {
        使用(VAR FS =新的FileStream(文件名,FileMode.Open,FileAccess.Read))
        {
            返回BitmapFrame.Create(
                FS,BitmapCreateOptions.None,BitmapCacheOption.OnLoad);
        }
    }
}

或者绑定到文件名属性与创建的BitmapImage或BitmapFrame如上所示的绑定转换器。

I have a simple Window with button and second Window is opened when I click on the Button. Second Window has a Image control, which displays a .png-file. So if I use FileObject property for Binding all is OK, I can delete file from File Explorer. But if I use FileName property for Binding I cannot delete file from File Explorer, I get OS exception. I cannot do this even if I close second window, even if I invoke GC explicitly. What is the problem with FileName property? Any ideas?

Win 7, Net 4.0

Window1

<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();
    }
}

Window2

<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();
    }
}

解决方案

When you bind the Image.Source property to an Uri (or a string, from which an Uri is created internally), WPF uses a built-in type converter that creates a BitmapFrame from the Uri.

If the Uri contains a path to a local file, the BitmapFrame keeps the file open, as long as it is existing. This may be longer than it is actually used in your application, because it may by cached by WPF.

When you need to be able to delete the file that an image was loaded from, you should always use your FileObject approach, but it should look like this:

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;
    }
}

Or like this:

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

Or you bind to the FileName property with a binding converter that creates a BitmapImage or BitmapFrame as shown above.

这篇关于WPF图像控制块中的文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆