2013-10-13 25 views
3

我的應用程序在屏幕上顯示圖像(圖像基於本地計算機上的文件),用戶可以根據需要將其刪除。在DataContext中使用時無法刪除文件

每次我試圖刪除它導致以下錯誤消息的文件:

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

我理解的錯誤消息。

我有一個UserControl它接受一個文件路徑(通過構造函數中的一個參數),然後綁定到它的(UserControl)DataContext

作爲調試此問題的一部分,我發現問題是由於在UserControl中設置DataContext。如果我從我的UserControl中刪除this.DataContext = this;,那麼我可以刪除該文件。

所以,我TestUnit看起來像

 Ui.UserControls.ImageControl ic = new ImageControl(
      @"C:\Users\Dave\Desktop\Duplicate\Swim.JPG"); 

     try 
     { 
      File.Delete(@"C:\Users\Dave\Desktop\Duplicate\Swim.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"); 
     } 
    } 

如果它的事項,我的用戶XAML使用 '圖像' 的控制,勢必 '文件路徑'

我已經嘗試使用UserControl null刪除之前,這沒有幫助。

我已經嘗試添加IDisposible接口到我的UserControl和Dispose()方法設置this.DataContext = null;但這並沒有幫助。

我在做什麼錯?我怎樣才能刪除這個文件(或者更準確地說,使它不被使用)。

+0

嘗試在刪除之前設置FilePath null。 – Paparazzi

+0

嗨@Blam,通過設置'this.DataContext = null;'它的FilePath爲空(FilePath是一個屬性)。但是,要真正確定,我也嘗試手動將其設置爲空,並且可悲的是它沒有任何區別。 – Dave

+0

將DataContext設置爲null並且從不分配它是不一樣的。 – Paparazzi

回答

4

問題不在於DataContext,而僅僅是WPF從文件加載圖像的方式。

當您綁定圖像控件包含一個文件路徑的字符串的Source財產,WPF內部創建從基本上是這樣的路徑中的新BitmapFrame對象:

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

不幸的是它可以使這個映像文件由WPF打開,所以你不能刪除它。

爲了解決這個問題,您必須將圖像屬性的類型更改爲ImageSource(或派生類型)並手動加載圖像,如下所示。

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:\Users\Dave\Desktop\Duplicate\Swim.JPG"); 
+0

謝謝你的回答,但作爲後續,你怎麼知道這是WPF所做的?似乎有圍繞這個社區的一些魔術/女巫手藝......你是否卸載了WPF DLL,或者是WPF代碼可以免費查看這種行爲? – Dave

+1

其實我不知道這是不是WPF所做的。但是,如果您使用調試器並在將其綁定到字符串時查看Image.Source屬性的值,則會看到它包含BitmapFrameDecode實例,這正是BitmapFrame.Create返回的內容。用另一種方法檢查並用本地文件調用BitmapFrame.Create Uri保持文件打開。當然,你仍然可以使用.NET Reflector這樣的工具,並將TypeConverter for ImageSource反彙編,以查看WPF真的在做什麼。 – Clemens

+0

最佳解決方案。奇蹟般有效!! – iamCR