首页 > 解决方案 > C#:DataGridView 数据源更新 - DataTable、List、BindingList 和 BindingSource?

问题描述

我仍然困惑于如何在更改 DataSource 的内容而不显式触发的情况下自动更新 DataGridView DataGridView.Update()DataTable, List, BindingListas (direct) DataSource 和 as (indirect) DataSource之间似乎没有任何区别,另外还有BindingSource一个使用前者作为 DataSource 的附加功能。

我实际使用的 DataGridView 是不可编辑的,只显示由相应实体代码更新的条目。我的最后一次尝试是BindingSource使用 aBindingList并在代码中操作 BindingSource 的内容。

我这里省略了一些方法,它们对基本问题没有作用。

形式:

private void FormLog_Load(object sender, EventArgs e) {
    ...
    dgvLog.DataSource = Log.Current.SourceEntries;
    ...
}

private void ClearLog() {
    Log.Current.RemoveAll();
}

public void UpdateDataSource() {
    dgvLog.Update();
}

实体(单例类):

public class LogEntry {
    public int ID { get; set; }
    public string DateTime { get; set; }
    public string Type { get; set; }
    public string Event { get; set; }
    public string Details { get; set; }
}

public class Log {
    public BindingList<LogEntry> Entries { get; set; }
    public BindingSource SourceEntries { get; set; }

public Log() {
    Entries = new BindingList<LogEntry>();
    SourceEntries = new BindingSource() { DataSource = Entries };
    ReadAll();
}

public void Add(string type, string logEvent, string details = "") {
    LogEntry entry = MapToDB(new LogEntry() {
        Type = type,
        Event = logEvent,
        Details = details
    });

    DB.Write(QueryAdd(entry));
    SourceEntries.Add(entry);

    if (Config.Current.GetForm("Log") != null)
        ((FormLog)Config.Current.GetForm("Log")).UpdateDataSource();
}

public void ReadAll() {
    for (int i = SourceEntries.Count - 1; i >= 0; i--) {
        SourceEntries.RemoveAt(i);
    }

    DataTable dt = DB.Read(QueryReadAll());
    if (dt != null) {
        foreach (DataRow row in dt.Rows) {
            SourceEntries.Add(MapToList(row));
        }
    }

    if (Config.Current.GetForm("Log") != null)
        ((FormLog)Config.Current.GetForm("Log")).UpdateDataSource();
}

public void RemoveAll() {
    DB.Write(QueryRemoveAll());

    for (int i = SourceEntries.Count - 1; i >= 0; i--) {
        SourceEntries.RemoveAt(i);
    }

    Add("I", "Log cleared");
}

这有效,但只有当我在另一个我想避免的单例类中使用自写的 FormStack 来调用UpdateSource()which 调用时。dgvLog.Update()当然,人们可以简单地dgvLog.Update()在表单本身内调用,但是,尤其是。通过这个日志示例,很明显,当显示 DataGridView 的表单仍在后台打开时,从另一个表单更新数据/在另一个表单内更新数据时,这无济于事。

此外,由于没有区别(使用 DataTable 或 List 等与 BindingSource 与否)我想知道 BindingList 和 BindingSource 的好处/目的是什么:

这是正确的方法还是我错过了什么!?

顺便说一句,我使用的是 .NET v4.5.2。

标签: c#winformsdatagridviewbindingdatasource

解决方案


似乎 DataTable、List、BindingList 作为(直接)DataSource 和作为(间接)DataSource 之间没有任何区别,而附加的 BindingSource 使用前者中的任何一个作为 DataSource。

BindingSource 有几个用途

  • 保持位置/当前行的知识,因此可以实现共享导航(dgv 和文本框都绑定到同一个 BS 意味着 dgv 可以浏览记录并且文本框更新,因为它们总是显示“当前行”)
  • 提供分类和过滤设施
  • 支持复杂的绑定场景,它必须帮助将列表过滤到不同绑定源中当前选定父级的唯一子级
  • 为通用数据源的多个不同位置浏览提供分离

有效,但仅当我调用 UpdateSource() 时,它通过在另一个我想避免的单例类中使用自写的 FormStack 来调用 dgvLog.Update()。当然,可以简单地在表单本身中调用 dgvLog.Update(),但是,尤其是。通过这个日志示例,很明显,当显示 DataGridView 的表单仍在后台打开时,从另一个表单更新数据/在另一个表单内更新数据时,这无济于事。

Datagridview.Update() 关注为需要它的控件重新绘制区域;它与提交对底层数据模型的更改无关。也许您需要 EndEdit 来完成对当前行的编辑操作并将它们提交到底层数据存储。当您单击网格中的不同行时也会发生这种情况。Bindingsource 也有一个 EndEdit 方法。大多数情况下,您不需要自己调用这些方法

要在表单之间共享数据,请传递存储数据的数据表,并通过第二种表单中的绑定源将其绑定

另外,由于没有区别(在使用 DataTable 或 List 等与 BindingSource 之间),我想知道 BindingList 和 BindingSource 的好处/目的是什么:

DataTable 是 DataRow 的集合。DataRow 的核心是一个对象数组。结束

绑定列表是您想要的任何内容的列表,例如您的自定义类 Person。可以说最终更有用,但它是在比较苹果和橙子。相反,如果您打开数据集设计器,那么您可以指定具有命名类型列的表。在这方面,它与编写自己的类并没有太大的不同(尽管它在短时间内编写了大量好的代码。我有时将它们用作数据模型


推荐阅读