2009-12-28 13 views
10

मैं XAML प्रिंट करने योग्य के क्षेत्रों बनाने की जरूरत है और इसलिए इस बटन हैंडलर बनाने के लिए है:क्या XAML तत्व की सटीक प्रति (क्लोन) प्राप्त करने के लिए कोई आसान/अंतर्निहित तरीका है?

private void Button_Click_Print(object sender, RoutedEventArgs e) 
{ 
    Customer.PrintReport(PrintableArea); 
} 

और PrintReport में मैं क्रम में एक से थोड़ा अलग तरीके से में इसे प्रिंट करने के लिए अन्य तत्वों में frameworkelement पैक यह स्क्रीन पर है, इस तरह:

public void PrintReport(FrameworkElement fwe) 
{ 
    StackPanel sp = new StackPanel(); 
    sp.Children.Add(fwe); 
    TextBlock tb = new TextBlock(); 
    tb.Text = "hello"; 
    sp.Children.Add(tb); 

    PrintDialog dialog = new PrintDialog(); 
    if (dialog.ShowDialog() == true) 
    { 
     dialog.PrintVisual(sp, "Print job"); 
    } 
} 

लेकिन ऊपर मेरा पीछा त्रुटि देता है:

निर्दिष्ट तत्व पहले से ही किसी अन्य तत्व के तार्किक बच्चे हैं। इसे पहले डिस्कनेक्ट करें।

वहाँ एक आसान तरीका FrameworkElement क्लोन करने के लिए इतना है कि मैं प्रति हेरफेर, यह मुद्रित कर सकते हैं, और फिर इसके बारे में भूल जाते हैं, XAML में मूल तत्व छोड़ने स्क्रीन बरकरार पर प्रदर्शित किया जा रहा है? मैं कल्पना होगा

कुछ इस तरह:

FrameworkElement fwe2 = FrameworkElement.Clone(fwe); //pseudo-code 

उत्तर

-1

मुझे यकीन है कि प्रति (माता-पिता, छपाई से अलग करने और वापस संलग्न को छोड़कर) करने के लिए आसान तरीका होना चाहिए हूँ। उदाहरण के लिए आप xaml लिखने के लिए XamlWriter आज़मा सकते हैं, और फिर इसे XamlReader के माध्यम से वापस पढ़ें। लेकिन मुझे संदेह है कि इस तरह कुछ बाध्यकारी और लेआउट त्रुटियां हो सकती हैं।

इसके बजाय मैं प्रिंट करने योग्य क्षेत्र का स्नैपशॉट लेने और इसे प्रिंट करने के लिए WriteableBitmap का उपयोग करने का प्रयास करूंगा। इस तरह आप रास्टर और ढीले वेक्टर बनाते हैं, लेकिन यह कहने के लिए प्रिंटिंग में पर्याप्त नहीं है कि यह अच्छा है या बुरा है। वैसे भी आप कोशिश कर सकते हैं और जांच :)।

चीयर्स, अंवाका।

6

मुझे अपने वर्तमान प्रोजेक्ट में एक ही समस्या थी और इसे इस कोड के साथ हल किया गया।

public static class ExtensionMethods 
{ 
    public static T XamlClone<T>(this T original) 
     where T : class 
    { 
     if (original == null) 
      return null; 

     object clone; 
     using (var stream = new MemoryStream()) 
     { 
      XamlWriter.Save(original, stream); 
      stream.Seek(0, SeekOrigin.Begin); 
      clone = XamlReader.Load(stream); 
     } 

     if (clone is T) 
      return (T)clone; 
     else 
      return null; 
    } 
} 

इस तरह यह बस अपने WPF परियोजना में सभी वस्तुओं पर एक तरीके के रूप में प्रकट होता है, तो आप विधि के लिए कोई पैरामीटर देने की जरूरत नहीं है, और यह मूल रूप में एक ही कक्षा की एक वस्तु देता है।

+4

इस दृष्टिकोण की सीमाएं हैं। Http://msdn.microsoft.com/en-us/library/ms754193.aspx देखें। – JeffFerguson

+0

यदि आप तत्व को उसी आकार में पुनर्स्थापित करना चाहते हैं तो फिर से 'क्लोन' कॉल करें। नया (0, 0, 0, मूलभूत। एक्टुअलविड्थ, ऑर्गेनल.एक्टुअल हाइट)) 'और 'क्लोन। अपडेटडेटा()' लेकिन आपको पहले डालना होगा यह 'UIElement' पर है। – Peter

3

डब्ल्यूपीएफ में, प्रतिलिपि (या "क्लोनिंग") तत्व लगभग कभी सही नहीं होते हैं। यह प्रभावी रूप से इसे XY Problem प्रश्न बनाता है। अर्थात। आप केवल सोचते हैं कि आपको सचमुच अपने दृश्य पेड़ में तत्वों को क्लोन करने की आवश्यकता है। लेकिन आप नहीं करते।

यहां पर बेवकूफ और सही दृष्टिकोण DataTemplate घोषित करना है जो उस डेटा का प्रतिनिधित्व करता है जिसे आप मुद्रित करना चाहते हैं। बेशक, इसका मतलब यह भी है कि जिस डेटा को आप प्रिंट करना चाहते हैं उसे बदले में एक मॉडल मॉडल वर्ग द्वारा दर्शाया जा रहा है, जिसके लिए DataTemplate घोषित किया गया है (यानी DataType संपत्ति के माध्यम से)।

उदाहरण के लिए:

<DataTemplate DataType={x:Type PrintableViewModel}> 
    <!-- template contents go here --> 
</DataTemplate> 

PrintableViewModel वर्ग जा रहा है, ज़ाहिर है, एक दृश्य मॉडल डेटा आप दृश्य पेड़ कि प्रिंट किया जाएगा पॉप्युलेट करने के लिए उपयोग करना चाहते हैं युक्त वर्ग।

<ContentControl Content={Binding PrintableViewModelProperty}/> 

यानी:

अपने यूआई के लिए XAML में, आप तो यह कुछ इस तरह का उपयोग करें वर्तमान DataContext ऑब्जेक्ट में Content संपत्ति को किसी संपत्ति पर बाध्य करें जो आपके PrintableViewModel का उदाहरण देता है, और ContentControl डेटा को उचित रूप से प्रदर्शित करने दें।

डब्ल्यूपीएफ उचित डेटा टेम्पलेट को देखेगा और इसे ContentControl में प्रदर्शित करने के लिए लागू करेगा। आप प्रिंट डेटा चाहते हैं, तो आप तो बस कुछ इस तरह करते हैं:

PrintDialog printDialog = new PrintDialog(); 

if (printDialog.ShowDialog() == true) 
{ 
    ContentControl contentControl = new ContentControl { Content = ((ViewModelClass)DataContext)PrintableViewModelProperty}; 

    // This part with the margins is not strictly relevant to your question per se, 
    // but it's useful enough to be worth including here for future reference 
    PageImageableArea area = printDialog.PrintQueue.GetPrintCapabilities(printDialog.PrintTicket).PageImageableArea; 

    contentControl.Margin = new Thickness(area.OriginWidth, area.OriginHeight, 
     printDialog.PrintableAreaWidth - area.ExtentWidth - area.OriginWidth, 
     printDialog.PrintableAreaHeight - area.ExtentHeight - area.OriginHeight); 

    // This shows retrieving the data template which is declared using the DataType 
    // property. Of course, if you simply declare a key and reference it explicitly 
    // in XAML, you can just use the key itself here. 
    DataTemplateKey key = new DataTemplateKey(typeof(MazeViewModel)); 

    contentControl.ContentTemplate = (DataTemplate)FindResource(key); 
    printDialog.PrintVisual(contentControl, "MazeGenerator"); 
} 

यह स्वचालित रूप से आप पहले से ही PrintableViewModel वर्ग के लिए का वर्णन किया है टेम्पलेट पुन: उपयोग करने WPF का कारण होगा, पॉप्युलेट ContentControl के दृश्य उस टेम्पलेट के अनुसार उप-पेड़, स्क्रीन पर प्रदर्शित दृश्य को डुप्लिकेट करना, लेकिन यूआई तत्वों के किसी भी प्रकार के स्पष्ट क्लोनिंग के बिना।


उपर्युक्त दर्शाता है कि दृश्य प्रतिनिधित्व का पुन: उपयोग कैसे करें। लेकिन निश्चित रूप से यदि आपके पास प्रिंटिंग के उद्देश्य के लिए आउटपुट को कस्टमाइज़ करने की इच्छा है, तो प्रिंट करने पर इस्तेमाल होने के लिए अलग-अलग DataTemplate घोषित करना उतना आसान है।

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

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