点击Window
时,我有一个简单的Window
按钮,第二个Button
被打开。第二个Window
有一个Image
控件,显示一个.png文件。因此,如果我对FileObject
使用Binding
属性,一切正常,我可以从File Explorer
删除文件。但是如果我对FileName
使用Binding
属性,我无法从File Explorer
删除文件,我会得到操作系统异常。即使我明确调用GC
,即使关闭第二个窗口,我也无法做到这一点。
FileName
属性有什么问题?有任何想法吗?
赢7,网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();
}
}
答案 0 :(得分:8)
当您将Image.Source
属性绑定到Uri(或从内部创建Uri的字符串)时,WPF使用内置类型转换器从Uri创建BitmapFrame
。
如果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,如上所示。
答案 1 :(得分:1)
使用此代码,我稍后会解释是什么问题。
var image = new BitmapImage();
image.BeginInit();
image.CacheOption = BitmapCacheOption.OnLoad;
image.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
image.UriSource = new Uri(FilePath);
image.EndInit();
return image;