2017-06-21 34 views
1

我有DataGrid而我設置的ItemsSourceObservableCollection<Dictionary<String, object>>的對象。使用ObservableCollection <Dictionary <String,Object >>作爲WPF中的DataGrid Itemsource

通常,我只是定義一個ClassA並將ObservableCollection<ClassA>設置爲ItemsSource,然後我可以將屬性名稱綁定到ClassA的列(DataGridTextColumn)。

但我不知道如何綁定字典的鍵/值。

有沒有什麼支持?

+0

您必須用尖括號放回泛型周圍的刻度,否則瀏覽器會認爲它們是標籤併吞下它們。提交後請閱讀你的問題,這樣你會發現這樣的錯誤。直到我爲您解決問題之後,您的問題纔有意義。 –

回答

3

的youre問什麼是相當複雜的,爲了創造一個ObservableDictionary<TKey, TValue>應創建一個實現類:

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

接口。 More in depth在這裏。這樣implemntion的一個例子是:

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 
    } 
} 

一個alterntive是本nice solution可綁定動態辭典的,即暴露每個字典條目作爲屬性。

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)); 
    } 
} 

然後你可以使用它像這樣:

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的需要自定義代碼構建列了起來:

XAML:

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

AutoGeneratedColumns事件:

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) });    
    }    
} 
相關問題