2017-06-21 49 views
1

私はDataGridを持っており、ItemsSourceObservableCollection<Dictionary<String, object>>オブジェクトです。WPFでObservableCollection <Dictionary <String、Object >>をDataGrid Itemsourceとして使用

通常、私はClassAを定義し、ObservableCollection<ClassA>をItemsSourceに設定すると、プロパティ名をClassAの列(DataGridTextColumn)にバインドできます。

しかし、辞書のキー/値のバインディング方法はわかりません。

サポートしていますか?

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

のインターフェイスを:youreの求めて何

+0

山括弧でジェネリックの周りにダニを置く必要があります。そうしないと、ブラウザはそれらがタグであり、それらを飲み込むと考えます。提出した後にあなたの質問をお読みください。そのようなエラーが見つかるでしょう。あなたの質問は私があなたのためにそれを修正するまで意味をなしませんでした。 –

答えて

3

は、実装するクラスを作成する必要がありObservableDictionary<TKey, TValue>を作成するためには、かなり複雑です。ここには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)); 
    } 
} 

次に、あなたがこのようにそれを使用することができます:

XAML:

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

AutoGeneratedColumnsイベント:

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が最大の列を構築するためのカスタムコードを必要とします

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) });    
    }    
} 
関連する問題