Binding DynamicObject a un DataGrid con generazione automatica delle colonne?
-
20-09-2019 - |
Domanda
Sono ancora sperimentando con DynamicObjects. Ora ho bisogno di alcune informazioni: Sto cercando di associare un oggetto che eredita dalla DynamicObject ad un WPF DataGrid (non Silverlight).
Come faccio ad avere il controllo DataGrid per creare automaticamente le sue colonne dalle proprietà pubbliche disponibili dell'oggetto che sono tipicamente generati in fase di esecuzione? È quello possibile in realtà?
Soluzione
Non c'è modo uniforme per interrogare le proprietà dinamiche, generalmente ci si aspetta che li conosci prima del tempo. Con DynamicObject
, gli esecutori possono annullare GetMemberNames
e che in genere ti dà le proprietà, tuttavia è davvero significava per il debug perché non v'è alcun obbligo che forniscono tutte le proprietà. In caso contrario, se è il proprio DynamicObject
non resta che scrivere il proprio metodo per ottenere le proprietà, sulla base di implementazione dinamica. Per esempio ExpandoObject
ti permette di interrogare tutte le proprietà utilizzando l'interfaccia IDictionary
.
Quindi, una volta che hai un modo per ottenere le proprietà è necessario dire al DataGrid. Purtroppo con un DataGrid, il problema di attuare ICustomTypeDescriptor
a dire il DataGrid sulle tue proprietà è che DataGrid ottiene i TypeDescriptors utilizzando il non Type dell'istanza, che è un problema per gli oggetti dinamici, tuttavia attuazione ITypedList
sulla raccolta di DynamicObjects funzionerà con il molto piccola Gotcha di se non si implementa l'interfaccia IList
non generico sulla vostra collezione, sarà spogliato fuori prima che arrivi al punto in cui si verifica la presenza di ITypeList
.
Quindi, in sintesi, implementare una Collezione con ITypedList
e IList
. Con nullo ritorno ITypedList
per GetListName
e solo implementare GetItemProperties(PropertyDescriptor[] listAccessors)
; Ignora listAccessors
e restituire un PropertyDescriptorCollection di PropertyDescriptors per ogni membro nominato sulla base della miglior rappresentato istanza di oggetto dinamico nel tuo elenco (molto probabilmente solo il primo oggetto). Tu devi implementare una sottoclasse di PropertyDescriptor, un modo semplice e generale alla / Set valore di ottenere è di utilizzare il framework opensource Dynamitey
using System;
using System.ComponentModel;
using Dynamitey;
public class DynamicPropertyDescriptor:PropertyDescriptor
{
public DynamicPropertyDescriptor(string name) : base(name, null)
{
}
public override bool CanResetValue(object component)
{
return false;
}
public override object GetValue(object component)
{
return Dynamic.InvokeGet(component, Name);
}
public override void ResetValue(object component)
{
}
public override void SetValue(object component, object value)
{
Dynamic.InvokeSet(component, Name, value);
}
public override bool ShouldSerializeValue(object component)
{
return false;
}
public override Type ComponentType
{
get { return typeof(object); }
}
public override bool IsReadOnly
{
get { return false; }
}
public override Type PropertyType
{
get
{
return typeof (object);
}
}
}
Altri suggerimenti
Credo che la DataGrid
utilizza TypeDescriptor
per ottenere le proprietà degli oggetti per creare le colonne. Così si dovrebbe essere in grado di raggiungere questo obiettivo se il vostro DynamicObject
implementa ICustomTypeDescriptor
. Implementare il metodo GetProperties
in modo che restituisca le proprietà dinamiche del vostro oggetto.