Search code examples
c#mvvm-light

C# Unable to delete a pdf that was previously open in a Window


I have a PDF file that is opened in window. The window is closed and then I try to delete the file and get an error that is in use. There should no longer be a lock on it since the window that had it open has been closed. Any advice would be greatly appreciated.

I have a local varaible _window

private Window _window;

I have the following code that opens a PDF in the window

_window = new Window
{
     Title = "PDF Viewer",
     Content = new WebBrowserView(),
     DataContext = new WebBrowserViewModel
     {
          Uri = _pdfPathFull
     },
     IsEnabled = false
 };

 _window.Show();

The window is closed as follows

private void ClosePDF()
{
     if (_window != null)
     {
          window.DataContext = new WebBrowserViewModel
          {
               Uri = "about:blank"
          };
          _window.Close();
          _window = null;
      }
}

I have the following code that tries to delete the file that was open in the window and it always fails with the error "The process cannot access the file \\ServerName\FileName.pdf because it is being used by another process."

ClosePDF();

bool fileDeleted = false;
int tryCount = 0;

FileInfo targetFile = new FileInfo(_pdfPathFull);
while (!fileDeleted && tryCount <= 50)
{
    System.Threading.Thread.Sleep(500);
    try
    {
        targetFile.Delete();
        fileDeleted = true;
    }
    catch(Exception ex)
    {
        if (tryCount == 50)
            throw (ex);
    }
    tryCount++;
}

Here is the definition for WebBrowserViewModel. This is all legacy code, I was just asked to add the delete functionality.

public class WebBrowserViewModel : AppViewModel
{
    private string _uri = string.Empty;

    public WebBrowserViewModel()
    {

    }

    public string Uri
    {
        get { return _uri; }
        set { Set("Uri", ref _uri, value); }
    }
}

Solution

  • I think the problem lies here:

    Doing this:

    DataContext = new WebBrowserViewModel
     {
          Uri = _pdfPathFull
     },
    

    creates an object in memory which continues to hold the pdf in reference even when the DataContext is set to "about:blank"

    I would suggest to take a reference Variable and use it instead. Make sure to de-reference it once the Window is closed. Make sure that the Window object is also cleaned up from the calling function.

    So this is how I would update the code:

    Add a new private variable:

    private Window _window;
    private FrameworkElement _fwElement;
    

    Next set of changes:

    _fwElement = new FrameworkElement();
    _fwElement.DataContext = new WebBrowserViewModel { Uri = _pdfPathFull };
    _window = new Window
    {
         Title = "PDF Viewer",
         Content = new WebBrowserView(),
         DataContext = _fwElement.DataContext,
         IsEnabled = false
     };
    
     _window.Show();
    

    Now when we close the Window:

    private void ClosePDF()
    {
         if (_window != null)
         {
              if(_fwElement != null)
              {
                 _fwElement.DataContext = null;
    
              }
              window.DataContext = new WebBrowserViewModel
              {
                   Uri = "about:blank"
              };
              _fwElement = null;
              _window.Close();
              _window = null;
              GC.Collect();
          }
    }