【问题标题】:How do I bind an ObservableCollection of Dictionaries to DataGrid?如何将 ObservableCollection 的字典绑定到 DataGrid?
【发布时间】:2021-05-29 15:25:39
【问题描述】:

我正在尝试了解如何将ObservableCollection<*Dictionary<string, DBRecord>> 绑定到DataGridItemSource 属性。

您可以在下面看到在内存中代表我的数据库表的类。我需要这样做,因为表架构是在独立的 .xml 文件中描述的(我无法更改)。

public abstract class DBField {
    public string Name;

    public DBField(string name) {
        Name = name;
    }
}

public class DBValueField<T> : DBField {
    public T Value;

    public DBValueField(string name, T value) : base(name) {
        Value = value;
    }
}

public class DBTextField : DBValueField<string> {
    public DBTextField(string name, string value) : base(name, value) { }
}

public class DBIntField : DBValueField<int> {
    public DBIntField(string name, int value) : base(name, value)
    {}
}

public class DBFloatField : DBValueField<float> {
    public DBFloatField(string name, float value) : base(name, value)
    {}
}

public class DBDoubleField : DBValueField<double> {
    public DBDoubleField(string name, double value) : base(name, value)
    {}
}

public class DBBoolField : DBValueField<bool> {
    public DBBoolField(string name, bool value) : base(name, value)
    {}
}

public class DBRecord {
    public Dictionary<string, DBField> Fields { get; set; }
}

public class DBTable {
    private readonly XmlSchema schema;
    public List<DBRecord> Records { get; set; }
}

这是我的数据库视图模型:

public class DatabaseViewModel : BaseViewModel {
    public Dictionary<string, DBTable> Tables { get; private set; }
    public DBTable ActiveTable { get; private set; }
    public ObservableCollection<DBRecord> ActiveData { get; set; }
}

我有一个 ComboBox,其中包含所有加载的数据库表的完整列表,并且我在该 ComboBox 下方有一个 DataGrid 元素。这个想法是,当您选择特定表时,ViewModel 将使用列(从表架构中检索)和值(值分配给 ActiveData 作为参考并从选定的组合框中的表)。 问题是我不明白如何正确地将这样的结构绑定到 DataGrid。

我的想法是:

  • 知道如何访问数据的转换器
  • 将数据映射到每个表的定制类(我真的想避免这种情况,因为不知道需要哪些表)
  • 以某种方式将字典集合绑定到 DataGrid(尝试这样做但不太明白如何做)
  • 以某种方式从代码隐藏中手动在 DataGrid 中插入行?

这是我的 WPF 标记:

<ComboBox x:Name="tablesComboBox"
        Grid.Row="0"
        Grid.Column="0"
        Grid.ColumnSpan="8"
        Style="{StaticResource DarkFlatComboBox}"
        ItemsSource="{Binding Tables, Mode=OneWay}"
        DisplayMemberPath="Key"
        SelectedValuePath="Value"
        SelectionChanged="ComboBox_SelectionChanged"/>

<DataGrid x:Name="dataGrid"
        Grid.Row="1"
        Grid.Column="0"
        Grid.ColumnSpan="8"
        AutoGenerateColumns="True"
        LoadingRow="DataGrid_LoadingRow"
        Style="{StaticResource DarkDataGrid}"
        ItemsSource="{Binding ActiveTable.Records,
                            Mode=TwoWay}"/>

【问题讨论】:

  • 不要这样做。展平/解构字典,使其成为一个简单的数据项列表。字典不是一个合理的数据源。这是一个特殊的集合,可提供非常快速的查找。大多数情况下,在 UI 中使用它会导致代码不自然且过于复杂(就像您的情况一样)。
  • @BionicCode Gotcha,试图做到这一点
  • @BionicCode 我设法用列表替换了字典。所以现在我绑定List&lt;DBRecord&gt; 转换为List&lt;List&lt;DBField&gt;&gt;。 DBField 有两个属性:Name 和 Value,其中 Name 是列名,Value 是该列的实际行值。如何正确设置 ItemsSource 的路径?
  • 不确定我是否正确理解您以及 DataGrid 应该如何呈现列表列表。通常您使用数据项列表作为数据源,其中每个项目显示为一行,该项目的每个属性构成一列。使用自动生成的表格,每个属性 name 都使列标题和属性值显示为单元格值。您可以手动定义列以自定义列名和/或属性映射和单元格布局。所以你想要的是List&lt;DBField&gt;
  • 或者从您的数据模型/数据库结果创建一个DataTable。您可以将其直接分配/绑定到DataGrid.ItemsSource

标签: c# wpf mvvm binding datagrid


【解决方案1】:

根据 BionicCode 的评论,我似乎试图通过创建 DataTableDataColumnDataRow 和其他类来重新发明轮子。

我删除了我的类,并将我的代码基于表的 System.Data 类。

此外,DataTable 完美绑定到 DataGrid,它解决了我的所有问题。

【讨论】:

    猜你喜欢
    • 2013-09-07
    • 2014-08-23
    • 2012-12-19
    • 1970-01-01
    • 2016-09-13
    • 2018-01-28
    • 2017-12-28
    • 2012-04-02
    相关资源
    最近更新 更多