बासी सवाल ताजा जवाब :)
पथ मैं वस्तुओं के रूप में अच्छी तरह से 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)।
मैंने अपने आवेदन में आर्किटेक्चर बदल दिया है, इसलिए यह अब मेरे लिए कोई मुद्दा नहीं है, लेकिन आपका जवाब सिर्फ इसे देखने के आधार पर प्रतीत होता है। –
किसी कारण से, मैंने पिछले साल इस जवाब को स्वीकार नहीं किया है। –