2009-05-19 21 views
26

मेरे पास 'गतिशील डेटा' का एक सेट है जिसे मुझे ग्रिडकंट्रोल से बांधने की आवश्यकता है। अब तक, मैं मानक डेटाटेबल क्लास का उपयोग कर रहा हूं जो सिस्टम का हिस्सा है। डेटा नामस्थान। इसने ठीक काम किया है, लेकिन मुझे बताया गया है कि मैं इसका उपयोग नहीं कर सकता क्योंकि यह क्लाइंट & सर्वर के बीच नेटवर्क पर क्रमबद्धता के लिए बहुत भारी है।डेटा बाध्यकारी गतिशील डेटा

तो मैंने सोचा कि मैं डेटाटेबल क्लास के 'कट-डाउन' संस्करण को आसानी से List<Dictionary<string, object>> के प्रकार से आसानी से दोहरा सकता हूं जिससे सूची पंक्तियों के संग्रह का प्रतिनिधित्व करती है, और प्रत्येक शब्दकोश कॉलम नामों और मानों के साथ एक पंक्ति का प्रतिनिधित्व करता है एक KeyValuePair प्रकार के रूप में। मैं तो बस जैसे मैं DataTable के स्तंभ नाम के लिए कर रहा था।

हालांकि

gridControl.DataSource = table; 
gridControl.RefreshDataSource(); 

ग्रिड होती है करने के बाद शब्दकोश (में कुंजी से मेल करने के लिए स्तंभ DataField गुणों से युक्त ग्रिड सेट कर सकते हैं कोई डेटा ...

मैं मैं IEnumerator लागू करने की आवश्यकता लगता है - इस पर किसी भी मदद की बहुत सराहना की जाएगी

उदाहरण बुला कोड इस तरह दिखता है:

var table = new List<Dictionary<string,object>>(); 

var row = new Dictionary<string, object> 
{ 
    {"Field1", "Data1"}, 
    {"Field2", "Data2"}, 
    {"Field3", "Data3"} 
}; 

table.Add(row); 

gridControl1.DataSource = table; 
gridControl1.RefreshDataSource(); 
+0

GridControl? क्या आपका मतलब डेटाग्रिड व्यू है? –

उत्तर

61

System.ComponentModel की अद्भुत दुनिया में आपका स्वागत है। .NET का यह अंधेरा कोना बहुत शक्तिशाली है, लेकिन बहुत जटिल है।

सावधानी का एक शब्द; जब तक कि आपके पास इसके लिए बहुत समय न हो - आप इसे किसी भी तंत्र में आसानी से क्रमबद्ध करने के लिए अच्छा कर सकते हैं, लेकिन इसे प्रत्येक छोर पर DataTable में फिर से बहाल करें ... बेहोश दिल के लिए क्या नहीं है; - पी

सबसे पहले - डेटा (तालिकाओं के लिए) बाध्यकारी सूचियों (IList/IListSource) के खिलाफ काम करता है - तो List<T> ठीक किया जाना चाहिए (संपादित: मैं कुछ पढ़ने में भूलना)। लेकिन यह समझने वाला नहीं है कि आपका शब्दकोश वास्तव में कॉलम है ...

कॉलम रखने का नाटक करने के लिए एक प्रकार प्राप्त करने के लिए आपको कस्टम PropertyDescriptor कार्यान्वयन का उपयोग करने की आवश्यकता है। ऐसा करने के कई तरीके हैं, इस पर निर्भर करते हुए कि कॉलम परिभाषाएं हमेशा समान होती हैं (लेकिन रनटाइम पर निर्धारित होती है, यानी शायद कॉन्फ़िगरेशन से), या क्या यह प्रति उपयोग में बदलती है (जैसे प्रत्येक DataTable उदाहरण में अलग-अलग कॉलम हो सकते हैं)।

"उदाहरण के प्रति" अनुकूलन के लिए, आप ITypedList में देखने की जरूरत है - यह जानवर (अलावा IList को में लागू) तालिका डेटा के लिए गुण पेश करने का मज़ा कार्य है ... लेकिन यह अकेले नहीं है:

"प्रकार प्रति" अनुकूलन के लिए, आप TypeDescriptionProvider देख सकते हैं - यह एक वर्ग के लिए गतिशील गुण का सुझाव कर सकते हैं ...

... या आप ICustomTypeDescriptor लागू कर सकते हैं - लेकिन यह केवल प्रयोग किया जाता है (सूचियों के लिए) में बहुत कभी-कभी परिस्थितियों (एक ऑब्जेक्ट इंडेक्सर (public object this[int index] {get;} ") और बाइंडिंग के बिंदु पर सूची में कम से कम एक पंक्ति)। (असतत वस्तुओं को बाध्य करते समय यह इंटरफ़ेस अधिक उपयोगी होता है - यानी सूचियां नहीं)।

ITypedList को लागू करने, और एक PropertyDescriptor मॉडल उपलब्ध कराने कड़ी मेहनत इसलिए यह बहुत ही कभी कभी किया जाता है ...। मैं इसके साथ काफी परिचित हूं, लेकिन मैं इसे हंसी के लिए नहीं करूँगा ...


यहाँ एक बहुत, बहुत सरल कार्यान्वयन (सभी स्तंभ स्ट्रिंग हैं, कोई सूचनाएं (वर्णनकर्ता के माध्यम से), कोई मान्यता (IDataErrorInfo) कोई भी रूपांतरण (TypeConverter), कोई अतिरिक्त सूची समर्थन (IBindingList/IBindingListView) , कोई अमूर्त (IListSource), कोई अन्य अन्य मेटाडाटा/गुण, आदि):

using System.ComponentModel; 
using System.Collections.Generic; 
using System; 
using System.Windows.Forms; 

static class Program 
{ 
    [STAThread] 
    static void Main() 
    { 
     Application.EnableVisualStyles(); 
     PropertyBagList list = new PropertyBagList(); 
     list.Columns.Add("Foo"); 
     list.Columns.Add("Bar"); 
     list.Add("abc", "def"); 
     list.Add("ghi", "jkl"); 
     list.Add("mno", "pqr"); 

     Application.Run(new Form { 
      Controls = { 
       new DataGridView { 
        Dock = DockStyle.Fill, 
        DataSource = list 
       } 
      } 
     }); 
    } 
} 
class PropertyBagList : List<PropertyBag>, ITypedList 
{ 
    public PropertyBag Add(params string[] args) 
    { 
     if (args == null) throw new ArgumentNullException("args"); 
     if (args.Length != Columns.Count) throw new ArgumentException("args"); 
     PropertyBag bag = new PropertyBag(); 
     for (int i = 0; i < args.Length; i++) 
     { 
      bag[Columns[i]] = args[i]; 
     } 
     Add(bag); 
     return bag; 
    } 
    public PropertyBagList() { Columns = new List<string>(); } 
    public List<string> Columns { get; private set; } 

    PropertyDescriptorCollection ITypedList.GetItemProperties(PropertyDescriptor[] listAccessors) 
    { 
     if(listAccessors == null || listAccessors.Length == 0) 
     { 
      PropertyDescriptor[] props = new PropertyDescriptor[Columns.Count]; 
      for(int i = 0 ; i < props.Length ; i++) 
      { 
       props[i] = new PropertyBagPropertyDescriptor(Columns[i]); 
      } 
      return new PropertyDescriptorCollection(props, true);    
     } 
     throw new NotImplementedException("Relations not implemented"); 
    } 

    string ITypedList.GetListName(PropertyDescriptor[] listAccessors) 
    { 
     return "Foo"; 
    } 
} 
class PropertyBagPropertyDescriptor : PropertyDescriptor 
{ 
    public PropertyBagPropertyDescriptor(string name) : base(name, null) { } 
    public override object GetValue(object component) 
    { 
     return ((PropertyBag)component)[Name]; 
    } 
    public override void SetValue(object component, object value) 
    { 
     ((PropertyBag)component)[Name] = (string)value; 
    } 
    public override void ResetValue(object component) 
    { 
     ((PropertyBag)component)[Name] = null; 
    } 
    public override bool CanResetValue(object component) 
    { 
     return true; 
    } 
    public override bool ShouldSerializeValue(object component) 
    { 
     return ((PropertyBag)component)[Name] != null; 
    } 
    public override Type PropertyType 
    { 
     get { return typeof(string); } 
    } 
    public override bool IsReadOnly 
    { 
     get { return false; } 
    } 
    public override Type ComponentType 
    { 
     get { return typeof(PropertyBag); } 
    } 
} 
class PropertyBag 
{ 
    private readonly Dictionary<string, string> values 
     = new Dictionary<string, string>(); 
    public string this[string key] 
    { 
     get 
     { 
      string value; 
      values.TryGetValue(key, out value); 
      return value; 
     } 
     set 
     { 
      if (value == null) values.Remove(key); 
      else values[key] = value; 
     } 
    } 
} 
+0

बहुत बढ़िया जवाब मैं इसे जाने दूंगा कि आपको कैसे पता चलेगा ... –

+3

ओच ... मेरी आंखें खून बह रही हैं। मैं डेटासेट और डायनामिक कॉलम संग्रह पर वापस जाता हूं: डी – Larry

+1

@ControlBreak - lol; एक बुद्धिमान विकल्प, मुझे संदेह है। –

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