首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在WPF中使用ObservableCollection<Dictionary<String、Object>>作为DataGrid Itemsource

在WPF中使用ObservableCollection<Dictionary<String、Object>>作为DataGrid Itemsource
EN

Stack Overflow用户
提问于 2017-06-21 02:05:08
回答 1查看 4.2K关注 0票数 2

我有一个DataGrid,我设置了ItemsSource是一个ObservableCollection<Dictionary<String, object>>对象。

通常,我只需定义一个ClassA并将ObservableCollection<ClassA>设置为ItemsSource,然后我就可以将属性名称绑定到ClassA的列(DataGridTextColumn)。

但我不知道如何绑定字典的键/值。

有什么支持吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-06-21 04:28:49

您所要求的是相当复杂的,为了创建ObservableDictionary<TKey, TValue>,您应该创建一个实现如下的类:

代码语言:javascript
运行
复制
IDictionary
INotifyCollectionChanged
INotifyPropertyChanged 
ICollection<KeyValuePair<TKey,TValue>>
IEnumerable<KeyValuePair<TKey,TValue>>
IEnumerable

接口。更深入在这里。这种实施的一个例子是:

代码语言:javascript
运行
复制
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
    }
}

可选的是一个可绑定动态字典的好的解决方案,它将每个字典条目公开为一个属性。

代码语言:javascript
运行
复制
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));
    }
}

然后你可以像这样使用它:

代码语言:javascript
运行
复制
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:

代码语言:javascript
运行
复制
<DataGrid AutoGenerateColumns="True" Name="dataGrid1" AutoGeneratedColumns="dataGrid1_AutoGeneratedColumns" />

AutoGeneratedColumns事件:

代码语言:javascript
运行
复制
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) });            
    }            
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44665733

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档