2009-09-18 16 views
9

WPF दस्तावेज़ व्यूअर में एक एक्सपीएस फ़ाइल दिखाने के बाद, और 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 doesn't release the XPS file में उल्लेख करता है, लेकिन है कि इस परिदृश्य में एक विकल्प नहीं है।

उत्तर

14

आप System.IO.Packaging.Package जहाँ से XpsDocument दर्शक को सौंपा खोला गया था बंद करने के लिए की जरूरत है। इसके अलावा, यदि आप उसी एप्लिकेशन सत्र में एक ही फ़ाइल को फिर से खोलने में सक्षम होना चाहते हैं, तो आपको पैकेजस्टोर से पैकेज को हटाना होगा। पैकेज को बंद करने से फ़ाइल लॉक जारी हो जाएगा और आपको फ़ाइल को हटाने की अनुमति मिल जाएगी, लेकिन फिर आप उसी फ़ाइल को फिर से खोलने में सक्षम नहीं होंगे (या, अधिक सटीक, उसी स्थान पर उसी फ़ाइल पर कोई भी फ़ाइल, भले ही उसके पास हो अलग-अलग सामग्री) जब तक आप पैकेजस्टोर से पैकेज को हटा नहीं देते।

प्रश्न में कोड के संदर्भ में, (प्रथम previewWindow.ShowDialog के बाद निम्नलिखित) सम्मिलित; फ़ाइल से पहले। डेलेटे (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 नहीं खुला था - नेट यह मुझे "के लिए" किया पीछे दृश्यों और खुद के बाद साफ करने के लिए भूल जाता है।

+0

इसने मुझे पकड़ा, मेरे पास एक दर्शक है जो एक दस्तावेज़ डाउनलोड करता है, एक बार दस्तावेज़ स्थापित करने के बाद यह इन परिवर्तनों को लागू करने के बाद भी असफल हो जाता है।जब मैं दस्तावेज़ लोड कर रहा था, तो मैं मूल दस्तावेज़ का निपटारा कर रहा था जो दस्तावेज़ को फिर से लोड करने के लिए रिलीज़ होने में रिलीज़ होने का कारण बनता था। –

4

सुनिश्चित नहीं हैं कि नेट के संस्करण इस सवाल मूल के संबंध में पूछा गया था, या यह है कि क्या 3.x और 4.x के बीच बदल दिया है सकते हैं, लेकिन नेट 4.0 के खिलाफ कुछ जांच से यह समाधान की तरह लग रहा हो सकता है इससे थोड़ा सा सरल हो।

XpsDocument IDisposable को लागू है, यह होने का निपटान() 'उपयोग के बाद घ की जरूरत का संकेत है। झुर्रियां यह है कि IDISposable.Dispose() लागू किया गया है जैसे कि यह छिपा हुआ है ताकि आप इसे सीधे कॉल नहीं कर सकें। आपको इसके बजाय बंद() को कॉल करने की आवश्यकता है। dotPeek का उपयोग XpsDocument.Dispose() का विश्लेषण करने के लिए:

  • XpsDocument.Close() XpsDocument.Dispose कॉल()
  • XpsDocument.Dispose() कॉल XpsManager.Close()
  • XpsManager.Close() कॉल XpsManager.RemovePackageReference()
  • XpsManager.RemovePackageReference() कॉल PackageStore.RemovePackage() और Package.Close()

तो जब तक मैं कुछ, बस बंद() XpsDocument (ing याद कर रहा हूँ जो आप ' डी को फिर से माना जाता है ओ वैसे भी) XpsDocument को संभालने के लिए आंतरिक पैकेज प्रबंधन सामग्री में खोदने के बिना एक ही परिणाम प्राप्त करना चाहिए।

+0

यह तर्कसंगत रूप से सबसे सरल दृष्टिकोण है! –