2012-02-25 11 views
8

को प्रश्नमुद्रण BlockUIContainer XpsDocument/FixedDocument

  1. आप कैसे एक FlowDocument कि BlockUIContainer प्रिंट करूं?
  2. मैं फ़्लो डॉक्यूमेंट पर एक उपाय/अपडेट/व्यवस्था कैसे कर सकता हूं?

पृष्ठभूमि

मैं एक जेनरेट किया है पाठ के पैराग्राफ के साथ FlowDocument एक संसाधन शब्दकोश से DrawingBrushes और BlockUIContainer भरा कस्टम नियंत्रण के साथ कुछ Rectangle तत्वों के साथ। जब FlowDocument * में से किसी में देखी

दस्तावेज़ सही ढंग से प्रस्तुत करने को नियंत्रित करता है हालांकि जब दस्तावेज़ FixedDocument/XpsDocument में बदल जाती है, Rectangle या BlockUIContainer तत्वों में से कोई भी प्रस्तुत करना।

मैं ऐसा इसलिए है क्योंकि नियंत्रण मापा नहीं किया गया है लगभग कुछ कर रहा हूँ/व्यवस्था की, तथापि को समझ नहीं सकता कैसे इससे पहले कि यह XpsDocument में बदल जाती है तो होना ही है कि मजबूर करने के लिए।

  • मैं LogicalTree रिकर्सिवली

    UIElement element = (UIElement)d; 
    element.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity)); 
    element.Arrange(new Rect(element.DesiredSize)); 
    element.UpdateLayout(); 
    

    चला गया है और निम्नलिखित किये, जहां d एक DependencyObject है। मैं देख सकता हूं कि यह डीबगर में ब्रेक-पॉइंट होने पर ActualWidth और ActualHeight गुण सेट करता है।

  • मैं के रूप में Will ♦ ने सुझाव दिया रेंडर करने के लिए मजबूर कर रहा Dispatcher कोशिश की है।

कोड XpsDocument

public class XpsDocumentConverter 
{ 

    public static XpsDocumentReference CreateXpsDocument(FlowDocument document) 
    { 
     // Need to clone the document so that the paginator can work 
     FlowDocument clonedDocument = DocumentHelper.Clone<FlowDocument>(document); 

     Uri uri = new Uri(String.Format("pack://temp_{0}.xps/", Guid.NewGuid().ToString("N"))); 
     MemoryStream ms = new MemoryStream(); 

     Package pkg = Package.Open(ms, FileMode.Create, FileAccess.ReadWrite); 
     PackageStore.AddPackage(uri, pkg); 
     XpsDocument xpsDocument = new XpsDocument(pkg, CompressionOption.Normal, uri.AbsoluteUri); 

     XpsSerializationManager rsm = new XpsSerializationManager(new XpsPackagingPolicy(xpsDocument), false); 
     DocumentPaginator paginator = new FixedDocumentPaginator(clonedDocument, A4PageDefinition.Default); 
     rsm.SaveAsXaml(paginator); 

     return new XpsDocumentReference(ms, xpsDocument); 
    } 

} 

मुद्रित करने के लिए आप मैं भी एक कस्टम DocumentPaginator 'FixedDocumentPaginator' नाम का उपयोग कर रहा देख सकते हैं इस्तेमाल किया; हालांकि मैं उस कोड को पोस्ट नहीं करूंगा क्योंकि मुझे संदेह है कि समस्या तब तक है जब तक यह GetPage(int pageNumber) में दस्तावेज़ को पेजिंग करना शुरू कर देता है, सब कुछ पहले से ही Visual रूपांतरित कर दिया गया है और यह लेआउट के लिए बहुत देर हो चुकी है।


संपादित

हम्म। जैसा कि मैंने इसे टाइप किया था, एक विचार सिर्फ मेरे सामने हुआ कि क्लोन दस्तावेज़ में Measure/Arrange/UpdateLayout नहीं हो सकता है।

प्रश्न: मैं फ़्लो डॉक्यूमेंट पर एक उपाय/अपडेट/व्यवस्था कैसे कर सकता हूं?

एक संभावित हैक जिसे मैं काम कर सकता हूं, क्लॉल्ड दस्तावेज़ को फ़्लो डॉक्यूमेंट व्यूअर (शायद ऑफ-स्क्रीन) में से एक में दिखाएगा।

एक अन्य संभावित समाधान है कि मैं सिर्फ के बारे में सीखा और प्रयास नहीं किया है कॉल करने के लिए होगा: ContextLayoutManager.From(Dispatcher.CurrentDispatcher).UpdateLayout();

ContextLayoutManager आप के लिए तार्किक पेड़ चलता है और लेआउट अद्यतन करता है।

कोड दस्तावेज़

public static FlowDocument Clone(FlowDocument originalDocument) 
{ 
    FlowDocument clonedDocument = new FlowDocument(); 
    TextRange sourceDocument = new TextRange(originalDocument.ContentStart, originalDocument.ContentEnd); 
    TextRange clonedDocumentRange = new TextRange(clonedDocument.ContentStart, clonedDocument.ContentEnd); 
    try 
    { 
     using (MemoryStream ms = new MemoryStream()) 
     { 
      sourceDocument.Save(ms, DataFormats.XamlPackage); 
      clonedDocumentRange.Load(ms, DataFormats.XamlPackage); 
     } 

     clonedDocument.ColumnWidth = originalDocument.ColumnWidth; 
     clonedDocument.PageWidth = originalDocument.PageWidth; 
     clonedDocument.PageHeight = originalDocument.PageHeight; 
     clonedDocument.PagePadding = originalDocument.PagePadding; 
     clonedDocument.LineStackingStrategy = clonedDocument.LineStackingStrategy; 

     return clonedDocument; 
    } 
    catch (Exception) 
    {    
    } 

    return null; 
} 

उत्तर

9

अन्य लोगों के साथ FlowDocument/FixedDocument/XpsDocument समान प्रतिपादन मुद्दों कर रहे है कि इस के लिए के रूप में भविष्य में संदर्भ के पोस्ट करना क्लोनिंग के लिए इस्तेमाल किया।

कुछ बातें ध्यान रखें:

  • BlockUIContainers क्लोन नहीं कर रहे हैं जब आप उपरोक्त विधि का उपयोग करें। यह तुरंत स्पष्ट जब तक मैं बाहर डिबग खिड़की तार्किक पेड़ मुद्रित कुछ सहायक विधियों (- वे अविश्वसनीय रूप से उपयोगी होते हैं इन तरीकों से नीचे पोस्ट कर रहे हैं) का उपयोग नहीं किया गया।
  • आप व्यूअर में दस्तावेज़ को प्रदर्शित करने और कुछ समय के लिए स्क्रीन पर दिखाने की जरूरत है। नीचे एक सहायक तरीका है जिसे मैंने मेरे लिए ऐसा करने के लिए लिखा था।

ForceRenderFlowDocument

private static string ForceRenderFlowDocumentXaml = 
@"<Window xmlns=""http://schemas.microsoft.com/netfx/2007/xaml/presentation"" 
      xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""> 
     <FlowDocumentScrollViewer Name=""viewer""/> 
    </Window>"; 

public static void ForceRenderFlowDocument(FlowDocument document) 
{ 
    using (var reader = new XmlTextReader(new StringReader(ForceRenderFlowDocumentXaml))) 
    { 
     Window window = XamlReader.Load(reader) as Window; 
     FlowDocumentScrollViewer viewer = LogicalTreeHelper.FindLogicalNode(window, "viewer") as FlowDocumentScrollViewer; 
     viewer.Document = document; 
     // Show the window way off-screen 
     window.WindowStartupLocation = WindowStartupLocation.Manual; 
     window.Top = Int32.MaxValue; 
     window.Left = Int32.MaxValue; 
     window.ShowInTaskbar = false; 
     window.Show(); 
     // Ensure that dispatcher has done the layout and render passes 
     Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Loaded, new Action(() => {})); 
     viewer.Document = null; 
     window.Close(); 
    } 
} 

संपादित करें: मैं सिर्फ विधि के लिए window.ShowInTaskbar = false जोड़ा जैसे कि आप जल्दी थे आप देख सकते हैं खिड़की टास्कबार में दिखाई देते हैं।

उपयोगकर्ता कभी भी "दृश्य" नहीं करेगा क्योंकि यह Int32.MaxValue पर ऑफ़-स्क्रीन पर स्थित है - एक चाल जो शुरुआती मल्टीमीडिया संलेखन (जैसे मैक्रोमीडिया/एडोब निदेशक) के साथ दिन में सामान्य थी।

इस प्रश्न को खोजने और ढूंढने वाले लोगों के लिए, मैं आपको बता सकता हूं कि दस्तावेज़ को प्रस्तुत करने के लिए कोई अन्य तरीका नहीं है।

दृश्य और तार्किक ट्री सहायकों

public static string WriteVisualTree(DependencyObject parent) 
{ 
    if (parent == null) 
     return "No Visual Tree Available. DependencyObject is null."; 

    using (var stringWriter = new StringWriter()) 
    using (var indentedTextWriter = new IndentedTextWriter(stringWriter, " ")) 
    {    
     WriteVisualTreeRecursive(indentedTextWriter, parent, 0); 
     return stringWriter.ToString(); 
    } 
} 

private static void WriteVisualTreeRecursive(IndentedTextWriter writer, DependencyObject parent, int indentLevel) 
{ 
    if (parent == null) 
     return; 

    int childCount = VisualTreeHelper.GetChildrenCount(parent); 
    string typeName = parent.GetType().Name; 
    string objName = parent.GetValue(FrameworkElement.NameProperty) as string; 

    writer.Indent = indentLevel; 
    writer.WriteLine(String.Format("[{0:000}] {1} ({2}) {3}", indentLevel, 
                   String.IsNullOrEmpty(objName) ? typeName : objName, 
                   typeName, childCount) 
        ); 

    for (int childIndex = 0; childIndex < childCount; ++childIndex) 
     WriteVisualTreeRecursive(writer, VisualTreeHelper.GetChild(parent, childIndex), indentLevel + 1); 
} 

public static string WriteLogicalTree(DependencyObject parent) 
{ 
    if (parent == null) 
     return "No Logical Tree Available. DependencyObject is null."; 

    using (var stringWriter = new StringWriter()) 
    using (var indentedTextWriter = new IndentedTextWriter(stringWriter, " ")) 
    { 
     WriteLogicalTreeRecursive(indentedTextWriter, parent, 0); 
     return stringWriter.ToString(); 
    } 
} 

private static void WriteLogicalTreeRecursive(IndentedTextWriter writer, DependencyObject parent, int indentLevel) 
{ 
    if (parent == null) 
     return; 

    var children = LogicalTreeHelper.GetChildren(parent).OfType<DependencyObject>(); 
    int childCount = children.Count(); 

    string typeName = parent.GetType().Name; 
    string objName = parent.GetValue(FrameworkElement.NameProperty) as string; 

    double actualWidth = (parent.GetValue(FrameworkElement.ActualWidthProperty) as double?).GetValueOrDefault(); 
    double actualHeight = (parent.GetValue(FrameworkElement.ActualHeightProperty) as double?).GetValueOrDefault(); 

    writer.Indent = indentLevel; 
    writer.WriteLine(String.Format("[{0:000}] {1} ({2}) {3}", indentLevel, 
                   String.IsNullOrEmpty(objName) ? typeName : objName, 
                   typeName, 
                   childCount) 
        ); 

    foreach (object child in LogicalTreeHelper.GetChildren(parent)) 
    { 
     if (child is DependencyObject) 
      WriteLogicalTreeRecursive(writer, (DependencyObject)child, indentLevel + 1); 
    } 

} 

प्रयोग

#if DEBUG 
    Debug.WriteLine("--- Start -------"); 
    Debug.WriteLine(VisualAndLogicalTreeHelper.WriteLogicalTree(document)); 
    Debug.WriteLine("--- End -------"); 
#endif 
+0

इस के लिए धन्यवाद, सिर्फ अपने आप को इस नरक के माध्यम से किया गया है, तो आप एक बहुत =) – JMK

+0

क्या 'XpsDocumentReference' में हो रहा है मदद की? मैं से प्रिंट करने का प्रयास रखना एक '' GetFixedDocumentSequence()। DocumentPaginator' के माध्यम से एक्सपीएस दस्तावेज़ से 'DocumentPaginator' खींच कर PrintDialog'। मुझे एक अमान्युरि अपवाद के परिणामस्वरूप एक एक्समल पार्स अपवाद मिलता है। जाहिर है कि निश्चित दस्तावेज यूआरआई किसी भी तरह उलझा हुआ है। –

+1

@ ऑस्टिनमुलिन्स http://stackoverflow.com/questions/9647401/documentviewer-to-richtextbox-binding-error पर मेरे उत्तर पर एक नज़र डालें, यह 'XpsDocumentReference' के कार्यान्वयन को दिखाता है। XPS को देखने के बाद से यह कुछ सालों से रहा है। पुन: प्रयास करने और मदद करने के लिए खुश।ओपन सोर्स लाइब्रेरी बनाने का यह एक अच्छा मौका होगा। – Dennis

4

मैं इस समाधान here पाया, और यह मुझे इसे बंद कर प्रस्तुत करने के लिए बिना FlowDocment की छपाई मिल में मदद की स्क्रीन ... तो मुझे उम्मीद है कि यह आपकी मदद कर सकता है !!

String copyString = XamlWriter.Save(flowDocViewer.Document); 
FlowDocument copy = XamlReader.Parse(copyString) as FlowDocument; 
+0

'XamlWriter.Save' के दौरान' BlockUIElement' में 'आइटम्स कंट्रोल' एम्बेड करते समय मैं एक अनंत रिकर्सन लूप में भाग गया। मुझे लगता है कि समस्या यह है कि आइटम्सकंट्रोल की कुछ संपत्ति इसके कंटेनर को संदर्भित करती है, और 'मार्कअपवाइटर.कॉर्डर्ड नामस्थान' फ़ंक्शन आइटम की प्रत्येक प्रॉपर्टी को फिर से सहेजने के लिए नेविगेट करता है। –

संबंधित मुद्दे