2009-09-18 7 views
9

Après avoir affiché un fichier XPS dans le document WPF DocumentViewer et fermé l'instance DocumentViewer, le fichier XPS est verrouillé et je ne peux pas le supprimer. J'ai besoin de libérer le verrou sur le fichier XPS afin que je puisse le supprimer, en écrire un autre avec le même nom, et éventuellement afficher ce nouveau fichier XPS dans une nouvelle instance de DocumentViewer. Je dois le faire dans la même instance d'application - sans avoir à fermer l'application (ceci est un scénario Aperçu avant impression). En d'autres termes, comment obtenir le code suivant à exécuter sans déclencher une exception à la "File.Delete (tempXpsFile);" déclaration?Comment faire pour que DocumentViewer de WPF libère son verrou de fichier sur le document XPS source?

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

Fermeture de l'application ne libère le verrou de fichier, comme mentionné dans WPF DocumentViewer doesn't release the XPS file, mais ce n'est pas une option dans ce scénario.

Répondre

14

Vous devez fermer le System.IO.Packaging.Package à partir duquel le XpsDocument affecté au visualiseur a été ouvert. En outre, si vous souhaitez pouvoir ouvrir à nouveau le même fichier dans la même session d'application, vous devrez supprimer le package du PackageStore. La fermeture du paquet libérera le verrou du fichier et vous permettra de le supprimer, mais vous ne pourrez pas rouvrir ce même fichier (ou, plus précisément, n'importe quel fichier du même nom portant le même nom, même s'il a contenu différent) jusqu'à ce que vous supprimiez le Package du PackageStore.

Dans le contexte du code dans la question, insérez ce qui suit après le premier previewWindow.ShowDialog(); avant le 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); 

Ainsi, le segment de code fixe présenté dans la question devient:

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

Oui, je sais que je ne l'ai pas ouvert la XpsDocument avec un package - NET a fait « pour » moi derrière la scènes et oublie de nettoyer après lui-même.

+0

Celui-ci m'a attrapé, j'ai un téléspectateur qui télécharge un document, une fois qu'il était en train de régler le document, il échouerait même après avoir appliqué ces changements.Lorsque je chargeais le document, je disposais le document original, ce qui provoquait l'échec de la publication lorsque je suis allé recharger le document. –

4

Vous ne savez pas quelle version de .Net cette question a été initialement posée par rapport à, ou si cela a peut-être changé entre 3.x et 4.x, mais d'une enquête sur .Net 4.0, il semble que la solution pourrait être un peu plus simple que cela.

XpsDocument implémente IDisposable, indiquant qu'il doit être Dispose() après utilisation. La ride est que IDisposable.Dispose() est implémenté de telle sorte qu'il est caché de sorte que vous ne pouvez pas l'appeler directement. Vous devez appeler Close() à la place. En utilisant dotPeek pour analyser XpsDocument.Dispose(): appels

  • XpsDocument.Close() appelle XpsDocument.Dispose()
  • XpsDocument.Dispose() appelle XpsManager.Close()
  • XpsManager.Close() XpsManager.RemovePackageReference()
  • XpsManager.RemovePackageReference() appelle PackageStore.RemovePackage() et Package.Close()

donc, à moins que je me manque quelque chose, il suffit de fermer() uant la XpsDocument (que vous est censé d Quoi qu'il en soit) devrait atteindre le même résultat sans avoir à creuser dans la gestion interne des paquets que XpsDocument devrait gérer.

+0

C'est sans doute l'approche la plus simple! –

Questions connexes