Tengo un conjunto de datos dinámica » que me necesita para unirse a la GridControl. Hasta ahora, he estado usando el estándar de la clase DataTable que es parte del Sistema.Datos de espacio de nombres. Esto ha funcionado bien, pero me han dicho que no puedo usar esto como que es demasiado pesado para la serialización a través de la red entre el cliente & servidor.

Así que pensé que podría fáciles de replicar un ‘corte’ de la versión de la clase DataTable por el simple hecho de tener un tipo de List<Dictionary<string, object>> cual la Lista representa la colección de filas, y cada Diccionario representa una fila con los nombres de las columnas y los valores como un KeyValuePair tipo. Yo podría configurar la Cuadrícula de la columna DataField propiedades que coinciden con los de las claves en el Diccionario (al igual que yo lo estaba haciendo por la tabla de datos de los nombres de columna.

Sin embargo después de hacer

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

La cuadrícula no tiene datos…

Yo creo que es necesario implementar IEnumerator – cualquier ayuda sería muy apreciada!

Ejemplo código de llamada se parece a esto:

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();
  • GridControl? A qué te refieres DataGridView?

1 Comentario

  1. 63

    Bienvenido al maravilloso mundo de Sistema.ComponentModel. Este oscuro rincón de .NET es muy potente, pero muy complejo.

    Una palabra de precaución; a menos que usted tiene un montón de tiempo para esto – usted puede hacer bien simplemente para serializar en cualquier mecanismo que se feliz con el, pero a hidratar en un DataTable en cada extremo… lo que sigue no es para los débiles de corazón ;-p

    En primer lugar – el enlace de datos (tablas) trabaja en contra de la listas (IList/IListSource) – así List<T> debe estar bien (editado: no entendí algo). Pero no va a entender que su diccionario es en realidad columnas…

    Para obtener un tipo de pretender que se tiene columnas que necesita para utilizar personalizado PropertyDescriptor implementaciones. Hay varias maneras de hacer esto, dependiendo de si las definiciones de columna son siempre las mismas (pero determinado en tiempo de ejecución, es decir, tal vez a partir de configuración), o si se cambia por el uso (por ejemplo, cómo cada DataTable instancia puede tener diferentes columnas).

    Por el «por ejemplo» la personalización, usted necesita mirar ITypedList – esta bestia (implementado en además a IList) tiene la divertida tarea de presentar propiedades para tabular los datos… pero no está solo:

    Por el «por tipo de personalización», se puede ver en TypeDescriptionProvider – esto puede sugerir las propiedades dinámicas de una clase…

    …o puede implementar ICustomTypeDescriptor – pero esto es sólo utilizado (para las listas) en muy circunstancias ocasionales (un objeto indexador (public object this[int index] {get;}«) y al menos una fila en la lista en el punto de unión). (esta interfaz es mucho más útil cuando la unión objetos discretos – es decir, no las listas).

    La aplicación de ITypedList, y proporcionando un PropertyDescriptor modelo es un trabajo duro… por lo tanto, sólo se hace muy de vez en cuando. Estoy bastante familiarizado con ella, pero yo no lo haría sólo por la risa…


    Aquí un muy, muy simplificado aplicación (todas las columnas son cadenas; sin notificaciones (a través de descriptores), validación (IDataErrorInfo), no hay conversiones (TypeConverter), no hay lista adicional de apoyo (IBindingList/IBindingListView), no la abstracción (IListSource), ningún otro tipo de metadatos/atributos, etc):

    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;
    }
    }
    }
    • Impresionante respuesta voy a darle una oportunidad de hacerle saber cómo me pongo en…
    • Ouch… Mis ojos están sangrando. Vuelvo a conjuntos de datos y columnas dinámicas colecciones 😀
    • lol; una sabia elección, sospecho.
    • ¿Cómo se podría solucionar el problema de la aplicación de muchos de los diferentes tipos sql en el ejemplo anterior? Sin usar el objeto..?
    • puede usted ser más específico? En particular, ¿cuándo empezamos a hablar sobre los tipos SQL? Feliz de ayudar, pero sin necesidad de contexto.
    • Ah lo siento, era tarde y estaba cansado. Quiero decir, ¿cómo puede el PropertyBag ser reescrito para almacenar y devolver los diferentes tipos? Es posible hacerlo sin tipo de objeto?
    • derecho; se puede hacer mucho más sofisticadas que las cosas con PropertyBag – usted necesidad justa de la PropertyDescriptor‘s PropertyType para devolver la cosa correcta. Sin embargo, como ya he mencionado – esto es esencialmente duplicar un montón de trabajo por lo que es poco a poco más cerca de lo que DataTable hace. No me gusta DataTable, pero es un ajuste razonable cuando el manejo de esquemas flexibles.
    • Ojalá pudiera upvote dos veces! 🙂

Dejar respuesta

Please enter your comment!
Please enter your name here