2009-05-08 22 views
5

द्वारा बनाई गई ऑब्जेक्ट का प्रकार ListCollectionView.AddNew कैसे बनाता है ऑब्जेक्ट का प्रकार निर्धारित करता है, और कोई इसे कैसे प्रभावित कर सकता है?ListCollectionView.AddNew

मैं कुछ प्रकार (Base, DerivedA, और DerivedB) के एक पदानुक्रम है, और वर्तमान में मेरे WPF टूलकिट DataGridDerivedA वस्तुओं बनाता है (क्यों, मैं नहीं जानता कि - शायद इसलिए है क्योंकि है ग्रिड में लगभग सभी डेटा उस प्रकार का), लेकिन मैं इसे DerivedB वस्तुओं को इसके बजाय बनाना चाहता हूं।

अद्यतन: मैं ListCollectionView से एक नया वर्ग पाने और इसके लिए एक नया AddNew विधि को लागू करने की कोशिश की है, और अब मैं लगभग वहाँ हूँ: ही शेष समस्या यह है कि एक नए आइटम जोड़ने के बाद, एक नया नया है आइटम प्लेसहोल्डर जोड़ा नहीं गया है, इसलिए मैं केवल एक आइटम जोड़ सकता हूं। मेरे वर्तमान दृष्टिकोण कुछ हद तक इस तरह दिखता है:

public class CustomView : ListCollectionView, IEditableCollectionView 
{ 
    public CustomView(System.Collections.IList list) 
     : base(list) 
    { 
    } 

    object IEditableCollectionView.AddNew() 
    { 
     DerivedB obj = new DerivedB(); 
     InternalList.Add(obj); 
     return obj; 
    } 
} 

उत्तर

4

बासी सवाल ताजा जवाब :)

पथ मैं वस्तुओं के रूप में अच्छी तरह से AddNew से जोड़ा जा रहा है को नियंत्रित करने के ले लिया ListCollectionView से एक वर्ग के व्युत्पन्न करता है लायक है, लेकिन ListCollectionView के स्रोत के माध्यम से ब्राउज़िंग के बाद

: पता लगाने के लिए क्या यह आंतरिक रूप से करता है, मैंने पाया कि सबसे सुरक्षित तरीका AddNew फिर से परिभाषित करने (यह तकनीकी रूप से एक ओवरराइड नहीं है) मेरी नई वस्तु बनाने के बाद ListCollectionView.AddNewItem उपयोग करने के लिए है, तो आपके कोड इस प्रकार दिखाई देगा है 10

इसका कारण यह है, इसके अलावा में अन्यथा दोनों कॉल AddNewCommon(object newItem) लगभग समान कार्यान्वयन होने, ListCollectionView.AddNew() और ListCollectionView.AddNewItem(object item) को अच्छी तरह से काम करता है:

public object AddNew() 
     { 
      VerifyRefreshNotDeferred(); 

      if (IsEditingItem) 
      { 
       CommitEdit(); // implicitly close a previous EditItem 
      } 

      CommitNew();  // implicitly close a previous AddNew 

      if (!CanAddNew) 
       throw new InvalidOperationException(SR.Get(SRID.MemberNotAllowedForView, "AddNew")); 

      return AddNewCommon(_itemConstructor.Invoke(null)); 
     } 

     public object AddNewItem(object newItem) 
     { 
      VerifyRefreshNotDeferred(); 

      if (IsEditingItem) 
      { 
       CommitEdit(); // implicitly close a previous EditItem 
      } 

      CommitNew();  // implicitly close a previous AddNew 

      if (!CanAddNewItem) 
       throw new InvalidOperationException(SR.Get(SRID.MemberNotAllowedForView, "AddNewItem")); 

      return AddNewCommon(newItem); 
     } 

AddNewCommon जहां सभी असली जादू होता है; घटनाओं फायरिंग, नया आइटम पर BeginInit और BeginEdit बुला यदि समर्थित है, और अंततः datagrid पर कॉलबैक के माध्यम से, सेल बाइंडिंग की स्थापना:

object AddNewCommon(object newItem) 
     { 
      _newItemIndex = -2; // this is a signal that the next Add event comes from AddNew 
      int index = SourceList.Add(newItem); 

      // if the source doesn't raise collection change events, fake one 
      if (!(SourceList is INotifyCollectionChanged)) 
      { 
       // the index returned by IList.Add isn't always reliable 
       if (!Object.Equals(newItem, SourceList[index])) 
       { 
        index = SourceList.IndexOf(newItem); 
       } 

       BeginAddNew(newItem, index); 
      } 

      Debug.Assert(_newItemIndex != -2 && Object.Equals(newItem, _newItem), "AddNew did not raise expected events"); 

      MoveCurrentTo(newItem); 

      ISupportInitialize isi = newItem as ISupportInitialize; 
      if (isi != null) 
      { 
       isi.BeginInit(); 
      } 

      IEditableObject ieo = newItem as IEditableObject; 
      if (ieo != null) 
      { 
       ieo.BeginEdit(); 
      } 

      return newItem; 
     } 

यहाँ मैं अपने TypedListCollectionView के स्रोत कोड को शामिल किया है, जो मैं करने के लिए उपयोग AddNew व्यवहार को नियंत्रित जब मैं नहीं जानता कि किस प्रकार डिजाइन समय की आवश्यकता होगी:

public class TypedListCollectionView : ListCollectionView, IEditableCollectionView 
    { 
     Type AddNewType { get; set; } 

     public TypedListCollectionView(System.Collections.IList source, Type addNewType) 
      : base(source) 
     { 
      AddNewType = addNewType; 
     } 

     object IEditableCollectionView.AddNew() 
     { 
      object newItem = Activator.CreateInstance(AddNewType); 
      return base.AddNewItem(newItem); 
     } 
    } 

मैं इस दृष्टिकोण की तरह है, क्योंकि यह ऐसे मामलों में जहां AddNew के प्रकार से कार्यावधि में समायोजित करने की आवश्यकता हो सकती है के लिए अधिकतम लचीलापन प्रदान करता है एक दूसरे को। यह संग्रह में पहला आइटम जोड़ने के लिए AddNew को भी काम करने की अनुमति देता है, जो सूची स्रोत प्रारंभ में खाली होने पर आसान होता है, लेकिन इसके अंतर्निहित प्रकार को निर्धारित किया जा सकता है।

This linkAddNew() द्वारा उपयोग किए जाने वाले प्रकार को बल देने के वैकल्पिक तरीके पर चर्चा करता है। यह निजी _itemConstructor प्रॉपर्टी को AddNew द्वारा निर्दिष्ट प्रकार के पैरामीटर रहित कन्स्ट्रक्टर में सेट करने के लिए प्रतिबिंब का उपयोग करता है।यह विशेष रूप से उपयोगी होगा जब आपका ListCollectionView आपके प्रभाव से बाहर एक घटक से आ रहा है, या आपको मौजूदा कोड में कार्यक्षमता जोड़ने की आवश्यकता है और आप चीजों को तोड़ने के बारे में चिंतित हैं (जो मैं कभी नहीं हूं क्योंकि मैं एक कमालियर कोडर हूं जो संग्रह के साथ carouses)।

+0

मैंने अपने आवेदन में आर्किटेक्चर बदल दिया है, इसलिए यह अब मेरे लिए कोई मुद्दा नहीं है, लेकिन आपका जवाब सिर्फ इसे देखने के आधार पर प्रतीत होता है। –

+0

किसी कारण से, मैंने पिछले साल इस जवाब को स्वीकार नहीं किया है। –

1

TomiJ,

देखें कि क्या वह मदद करता है, लेकिन इस सवाल का जवाब ठीक नहीं है?

http://www.cnblogs.com/winkingzhang/archive/2008/05/22/1204581.html

+1

आलेख (मूल एक पर है) कुछ लोगों में से था मदद, क्योंकि उसने मुझे 'ListCollectionView' को देखने से रोक दिया था। –

+0

मैं देखता हूं, मैं आपको सही उत्तर प्राप्त करने में कामयाब रहा हूं, यहां अपडेट करना न भूलें। यह एक बहुत ही रोचक सवाल है: डी –

+0

मैं अभी तक काफी नहीं हूं, क्योंकि मैं केवल _one_ नई वस्तु जोड़ सकता हूं, लेकिन कम से कम सही AddNew विधि को कॉल किया जाता है। मुझे यह समझना होगा कि उचित कार्यक्षमता प्राप्त करने के लिए मुझे और क्या करना है। –

1

.NET 4 में, अब एक नया इंटरफ़ेस IEditableCollectionViewAddNewItem है, जिसे ListCollectionView द्वारा कार्यान्वित किया गया है, जिसमें एक नई विधि AddNewItem(object) है। नए जोड़े गए आइटम को नियंत्रित करने के लिए आप इसे AddNew() के बजाय उपयोग कर सकते हैं।

+0

दरअसल, और यह उत्तर उतना ही ठीक है जितना कि एरिकेस्ट से मैंने स्वीकार किया है (उस उत्तर के आधार पर पुराने और 'ListCollectionView.AddNewItem (ऑब्जेक्ट)' का उल्लेख भी किया गया है। –