9

WPF DocumentViewer で XPS ファイルを表示し、DocumentViewer インスタンスを閉じた後、XPS ファイルがロックされ、削除できません。XPS ファイルのロックを解除して、XPS ファイルを削除し、同じ名前で別のファイルを書き込んで、必要に応じてその新しい XPS ファイルを新しい DocumentViewer インスタンスに表示できるようにする必要があります。アプリを閉じることなく、同じアプリ インスタンスでこれを行う必要があります (これは印刷プレビューのシナリオです)。

つまり、「File.Delete(tempXpsFile);」で例外をスローせずに次のコードを実行するにはどうすればよいでしょうか。声明?

var tempXpsFile = @"c:\path\to\Temporary.xps";

var previewWindow = new Window();
var docViewer = new DocumentViewer();
previewWindow.Content = docViewer;

GenerateXpsFile(tempXpsFile);

var xpsDocument = new XpsDocument(tempXpsFile);

previewWindow.ShowDialog();

File.Delete(tempXpsFile);  //this will throw an exception due to a file lock on tempXpsFile

GenerateXpsFile(tempXpsFile); //assume this generates a different file
//otherwise the scenario doesn't make sense as we could just skip the above delete
//and this statement and re-use the same file

previewWindow = new Window();
docViewer = new DocumentViewer();
previewWindow.Content = docViewer;

previewWindow.ShowDialog();

WPF DocumentViewer does not release the XPS fileで説明されているように、アプリを閉じるとファイル ロックが解除されますが、このシナリオではオプションではありません。

4

2 に答える 2

14

ビューアーに割り当てられた XpsDocument を開いた System.IO.Packaging.Package を閉じる必要があります。さらに、同じアプリケーション セッション内で同じファイルを再度開くことができるようにする場合は、PackageStore からパッケージを削除する必要があります。パッケージを閉じると、ファイルのロックが解除され、ファイルを削除できるようになりますが、同じファイル (または、より正確には、同じ場所にある同じ名前のファイル) を再度開くことはできなくなります。別のコンテンツ) を PackageStore からパッケージを削除するまで。

質問のコードのコンテキストでは、最初の previewWindow.ShowDialog(); の後に次を挿入します。File.Delete(tempXpsFile); の前に

//Get the Uri from which the system opened the XpsPackage and so your XpsDocument
var myXpsUri = xpsDocument.Uri; //should point to the same file as tempXpsFile

//Get the XpsPackage itself
var theXpsPackage = System.IO.Packaging.PackageStore.GetPackage(myXpsUri);

//THIS IS THE KEY!!!! close it and make it let go of it's file locks
theXpsPackage.Close();

//if you don't remove the package from the PackageStore, you won't be able to
//re-open the same file again later (due to System.IO.Packaging's Package store/caching
//rather than because of any file locks)
System.IO.Packaging.PackageStore.RemovePackage(myXpsUri);

したがって、質問に示されている固定コード セグメントは次のようになります。

var tempXpsFile = @"c:\path\to\Temporary.xps";

var previewWindow = new Window();
var docViewer = new DocumentViewer();
previewWindow.Content = docViewer;

GenerateXpsFile(tempXpsFile);

var xpsDocument = new XpsDocument(tempXpsFile);

previewWindow.ShowDialog();

//BEGIN NEW CODE
var myXpsUri = xpsDocument.Uri; //should point to the same file as tempXpsFile
var theXpsPackage = System.IO.Packaging.PackageStore.GetPackage(myXpsUri);
theXpsPackage.Close();
System.IO.Packaging.PackageStore.RemovePackage(myXpsUri);
//END NEW CODE

File.Delete(tempXpsFile);  //this will succeed now

GenerateXpsFile(tempXpsFile);

previewWindow = new Window();
docViewer = new DocumentViewer();
previewWindow.Content = docViewer;

previewWindow.ShowDialog();

はい、XpsDocument をパッケージで開いていないことはわかっています。

于 2009-09-18T04:34:26.240 に答える