2017-06-21 2 views
1

Ich habe eine DataGrid und ich setze ItemsSource ist ein ObservableCollection<Dictionary<String, object>> Objekt.Verwenden von ObservableCollection <Dictionary <String, Object >> als DataGrid Itemsource in WPF

Normalerweise definiere ich einfach einen ClassA und setze ObservableCollection<ClassA> auf ItemsSource, dann kann ich den Namen der Eigenschaften an Spalten (DataGridTextColumn) von ClassA binden.

Aber ich weiß nicht, wie man einen Schlüssel/Wert eines Dictionary bindet.

Haben Sie Unterstützung?

+0

Sie müssen Ticks um Generika mit spitzen Klammern setzen, oder der Browser wird denken, dass sie Tags sind und sie schlucken. Bitte lesen Sie Ihre Fragen nach dem Absenden, damit Sie Fehler wie diese finden. Deine Frage ergab keinen Sinn, bis ich es für dich repariert habe. –

Antwort

3

Was youre fragen, ist ziemlich komplex, um ObservableDictionary<TKey, TValue> zu erstellen sollte man eine Klasse erstellen, implementiert:

IDictionary 
INotifyCollectionChanged 
INotifyPropertyChanged 
ICollection<KeyValuePair<TKey,TValue>> 
IEnumerable<KeyValuePair<TKey,TValue>> 
IEnumerable 

Schnittstellen. More in depth hier drin. Ein Beispiel einer solchen implemntion ist:

class ObservableDictionary<TKey, TValue> : IDictionary, INotifyCollectionChanged, INotifyPropertyChanged 
{ 
    private Dictionary<TKey, TValue> mDictionary; 

    //Methods & Properties for IDictionary implementation would defer to mDictionary: 
    public void Add(TKey key, TValue value) 
    { 
     mDictionary.Add(key, value); 
     OnCollectionChanged(NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, value) 
     return; 
    } 

    //Implementation of INotifyCollectionChanged: 
    public event NotifyCollectionChangedEventHandler CollectionChanged; 
    protected void OnCollectionChanged(NotifyCollectionChangedEventArgs args) 
    { 
     //event fire implementation 
    } 

    //Implementation of INotifyProperyChanged: 
    public event ProperyChangedEventHandler ProperyChanged; 
    protected void OnPropertyChanged(PropertyChangedEventArgs args) 
    { 
     //event fire implementation 
    } 
} 

Ein alterntive ist dies nice solution eines bindungsfähigen dynamischen Wörterbuch, dass jedes Wörterbucheintrag als eine Eigenschaft aus.

public sealed class BindableDynamicDictionary : DynamicObject, INotifyPropertyChanged 
{ 
    /// <summary> 
    /// The internal dictionary. 
    /// </summary> 
    private readonly Dictionary<string, object> _dictionary; 

    /// <summary> 
    /// Creates a new BindableDynamicDictionary with an empty internal dictionary. 
    /// </summary> 
    public BindableDynamicDictionary() 
    { 
     _dictionary = new Dictionary<string, object>(); 
    } 

    /// <summary> 
    /// Copies the contents of the given dictionary to initilize the internal dictionary. 
    /// </summary> 
    public BindableDynamicDictionary(IDictionary<string, object> source) 
    { 
     _dictionary = new Dictionary<string, object>(source); 
    } 

    /// <summary> 
    /// You can still use this as a dictionary. 
    /// </summary> 
    public object this[string key] 
    { 
     get { return _dictionary[key]; } 
     set 
     { 
      _dictionary[key] = value; 
      RaisePropertyChanged(key); 
     } 
    } 

    /// <summary> 
    /// This allows you to get properties dynamically. 
    /// </summary> 
    public override bool TryGetMember(GetMemberBinder binder, out object result) 
    { 
     return _dictionary.TryGetValue(binder.Name, out result); 
    } 

    /// <summary> 
    /// This allows you to set properties dynamically. 
    /// </summary> 
    public override bool TrySetMember(SetMemberBinder binder, object value) 
    { 
     _dictionary[binder.Name] = value; 
     RaisePropertyChanged(binder.Name); 
     return true; 
    } 

    /// <summary> 
    /// This is used to list the current dynamic members. 
    /// </summary> 
    public override IEnumerable<string> GetDynamicMemberNames() 
    { 
     return _dictionary.Keys; 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    private void RaisePropertyChanged(string propertyName) 
    { 
     var propChange = PropertyChanged; 
     if (propChange == null) return; 
     propChange(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

Dann können Sie es wie folgt verwenden:

private void testButton1_Click(object sender, RoutedEventArgs e) 
{ 
    var dd = new BindableDynamicDictionary(); // Creating a dynamic dictionary. 
    dd["Age"] = 32; //access like any dictionary 

    dynamic person = dd; //or as a dynamic 
    person.FirstName = "Alan"; // Adding new dynamic properties. The TrySetMember method is called. 
    person.LastName = "Evans"; 

    //hacky for short example, should have a view model and use datacontext 
    var collection = new ObservableCollection<object>(); 
    collection.Add(person); 
    dataGrid1.ItemsSource = collection; 
} 

Datagrid braucht individuelle Code für die Spalten Aufbau:

XAML:

<DataGrid AutoGenerateColumns="True" Name="dataGrid1" AutoGeneratedColumns="dataGrid1_AutoGeneratedColumns" /> 

AutoGeneratedColumns Veranstaltung:

private void dataGrid1_AutoGeneratedColumns(object sender, EventArgs e) 
{ 
    var dg = sender as DataGrid; 
    var first = dg.ItemsSource.Cast<object>().FirstOrDefault() as DynamicObject; 
    if (first == null) return; 
    var names = first.GetDynamicMemberNames(); 
    foreach(var name in names) 
    { 
     dg.Columns.Add(new DataGridTextColumn { Header = name, Binding = new Binding(name) });    
    }    
} 
Verwandte Themen