2008-08-28 13 views
34

किसी के पास एक अच्छा उदाहरण है कि डब्ल्यूपीएफ ऑब्जेक्ट को गहरा क्लोन कैसे करें, डाटाबेसिंग को संरक्षित किया जाए?आप एक WPF ऑब्जेक्ट को क्लोन कैसे कर सकते हैं?


चिह्नित उत्तर पहला भाग है।

दूसरा भाग यह है कि आपको अभिव्यक्ति कनवर्टर बनाना है और इसे क्रमबद्ध प्रक्रिया में इंजेक्ट करना है। इस के लिए विवरण यहां हैं:
http://www.codeproject.com/KB/WPF/xamlwriterandbinding.aspx?fid=1428301&df=90&mpp=25&noise=3&sort=Position&view=Quick&select=2801571

उत्तर

53

मैंने किया है सबसे आसान तरीका है WPF ऑब्जेक्ट को स्ट्रिंग के रूप में सहेजने के लिए XamlWriter का उपयोग करना। सहेजें विधि वस्तु और उसके सभी बच्चों को तार्किक पेड़ में क्रमबद्ध करेगी। अब आप एक नई वस्तु बना सकते हैं और इसे XamlReader के साथ लोड कर सकते हैं।

पूर्व: एक नई वस्तु में

string gridXaml = XamlWriter.Save(myGrid); 

लोड यह: XAML करने के लिए वस्तु लिखें (मान लीजिए कि वस्तु एक ग्रिड नियंत्रण था)

StringReader stringReader = new StringReader(gridXaml); 
XmlReader xmlReader = XmlReader.Create(stringReader); 
Grid newGrid = (Grid)XamlReader.Load(xmlReader); 
+1

ध्यान रखें कि यह भी नाम है जो यूआई तत्वों के लिए उनके उपयोग करते हुए पेचीदा हो अगर वे रखा जाना एक ही रूट कंटेनर है क्लोन। – toad

+0

मुझे नहीं लगता कि यह एनिमेशन को संरक्षित करता है, है ना? –

+7

स्पष्ट होने के लिए, यह केवल आधा समाधान है (क्योंकि यह 08 में वापस खड़ा था)। इससे बाइंडिंग का मूल्यांकन किया जाएगा और परिणाम क्रमबद्ध किए जाएंगे। अगर आप बाइंडिंग को संरक्षित करना चाहते हैं (प्रश्न के रूप में पूछा गया) आपको या तो रनटाइम पर बाध्यकारी प्रकार में एक अभिव्यक्ति कनवर्टर जोड़ना होगा (प्रासंगिक लिंक के लिए मेरे प्रश्न का दूसरा भाग देखें) या 4.0 में इसे कैसे करें इसके लिए नीचे अपना स्वयं का उत्तर देखें। – Will

-1

कैसे के बारे में:

public static T DeepClone<T>(T from) 
    { 
     using (MemoryStream s = new MemoryStream()) 
     { 
      BinaryFormatter f = new BinaryFormatter(); 
      f.Serialize(s, from); 
      s.Position = 0; 
      object clone = f.Deserialize(s); 

      return (T)clone; 
     } 
    } 
बेशक

इस गहरे क्लोन किसी भी वस्तु, और यह शहर में सबसे तेजी से समाधान नहीं हो सकता है, लेकिन यह कम से कम रखरखाव है .. :)

+4

इस WPF वस्तुओं = के लिए काम नहीं करता है ( –

30

.NET 4.0, में नया xaml serialization ढेर यह बहुत आसान बनाता है।

var sb = new StringBuilder(); 
var writer = XmlWriter.Create(sb, new XmlWriterSettings 
{ 
    Indent = true, 
    ConformanceLevel = ConformanceLevel.Fragment, 
    OmitXmlDeclaration = true, 
    NamespaceHandling = NamespaceHandling.OmitDuplicates, 
}); 
var mgr = new XamlDesignerSerializationManager(writer); 

// HERE BE MAGIC!!! 
mgr.XamlWriterMode = XamlWriterMode.Expression; 
// THERE WERE MAGIC!!! 

System.Windows.Markup.XamlWriter.Save(this, mgr); 
return sb.ToString(); 
+0

मुझे नहीं लगता कि यह XamlWriter का उपयोग करने से अलग कैसे है। बचाओ? डेटाग्रिड को क्रमबद्ध करने की कोशिश करते समय कम से कम मुझे कोई अलग परिणाम नहीं दिखाई दिए। –

+4

@ जेपी क्षमा करें, यह सब स्पष्ट नहीं है .... सवाल यह था कि बाइंडिंग को संरक्षित करते समय * क्लोन कैसे करें *। चिह्नित उत्तर आधा सही है; वास्तव में, यदि आप ऐसा करते हैं तो आप पाएंगे कि आपके बाइंडिंग का मूल्यांकन किया जाएगा और नतीजे (बाइंडिंग स्वयं नहीं) को क्रमबद्ध किया जाएगा।मेरे प्रश्न में, मैंने समाधान के लिए दूसरा आधा जोड़ा, जो एक अभिव्यक्ति कनवर्टर जोड़ना है और इसे रनटाइम पर बाध्यकारी प्रकार में जोड़ना है। यह थोड़ा अस्पष्ट है। इस जवाब से वही काम पूरा किया जा सकता है - यहां मैजिक टिप्पणी देखें? यह धारावाहिक के दौरान बाइंडिंग का मूल्यांकन करने के लिए ** ** ** धारावाहिक को निर्देशित करता है। साफ। – Will

+0

हां, मैंने यह देखा। मैं अभी भी अपने डाटाग्रिड के साथ एक ही समस्या पर काम कर रहा हूं और डेटा बाइंडिंग के संबंध में कोई अलग परिणाम नहीं देखा। मेरा डाटाग्रिड अभी भी खाली है। मुझे कुछ और याद आना चाहिए। कोई भी कम नहीं, मैं आपको यह सब इंगित करने के लिए एक उपेक्षा दूंगा। –

4

यहां कुछ शानदार उत्तर दिए गए हैं। बहुत उपयोगी। मैंने बाध्यकारी जानकारी की प्रतिलिपि बनाने के लिए विभिन्न दृष्टिकोणों की कोशिश की थी, जिसमें http://pjlcon.wordpress.com/2011/01/14/change-a-wpf-binding-from-sync-to-async-programatically/ में उल्लिखित दृष्टिकोण शामिल है लेकिन यहां की जानकारी इंटरनेट पर सबसे अच्छी है!

मैं InvalidOperationException के साथ काम कर "बाइंडिंग बदला नहीं जा सकता यह प्रयोग किया गया है के बाद।" मेरे परिदृश्य में, मैं बनाए रखने गया था कुछ कोड किसी ने लिखा है के लिए एक फिर से प्रयोग करने योग्य विस्तार विधि बनाया है, और एक प्रमुख DevExpress DXGrid ढांचे अपग्रेड करने के बाद, यह अब काम नहीं किया निम्नलिखित ने मेरी समस्या को पूरी तरह से हल किया। कोड का हिस्सा जहां मैं ऑब्जेक्ट वापस करता हूं, अच्छा हो सकता है, और मैं बाद में फिर से कारक बनाउंगा।

/// <summary> 
/// Extension methods for the WPF Binding class. 
/// </summary> 
public static class BindingExtensions 
{ 
    public static BindingBase CloneViaXamlSerialization(this BindingBase binding) 
    { 
     var sb = new StringBuilder(); 
     var writer = XmlWriter.Create(sb, new XmlWriterSettings 
     { 
      Indent = true, 
      ConformanceLevel = ConformanceLevel.Fragment, 
      OmitXmlDeclaration = true, 
      NamespaceHandling = NamespaceHandling.OmitDuplicates, 
     }); 
     var mgr = new XamlDesignerSerializationManager(writer); 

     // HERE BE MAGIC!!! 
     mgr.XamlWriterMode = XamlWriterMode.Expression; 
     // THERE WERE MAGIC!!! 

     System.Windows.Markup.XamlWriter.Save(binding, mgr); 
     StringReader stringReader = new StringReader(sb.ToString()); 
     XmlReader xmlReader = XmlReader.Create(stringReader); 
     object newBinding = (object)XamlReader.Load(xmlReader); 
     if (newBinding == null) 
     { 
      throw new ArgumentNullException("Binding could not be cloned via Xaml Serialization Stack."); 
     } 

     if (newBinding is Binding) 
     { 
      return (Binding)newBinding; 
     } 
     else if (newBinding is MultiBinding) 
     { 
      return (MultiBinding)newBinding; 
     } 
     else if (newBinding is PriorityBinding) 
     { 
      return (PriorityBinding)newBinding; 
     } 
     else 
     { 
      throw new InvalidOperationException("Binding could not be cast."); 
     } 
    } 
}