如何以最有效的方式在datagridview中填充一个生成的列?

问题描述 投票:0回答:2

我在Winforms程序中设置了一个DataGridView,信息是从数据库中填充的。

我在数据表格中使用了 Select * FROM [Data] 与以下代码。

        private void GetData(string selectCommand)
        {
            try
            {
                // Create a new data adapter based on the specified query.
                dataAdapter = new OleDbDataAdapter(selectCommand, strConn);

                // Create a command builder to generate SQL update, insert, and
                // delete commands based on selectCommand.
                OleDbCommandBuilder commandBuilder = new OleDbCommandBuilder(dataAdapter);

                // Populate a new data table and bind it to the BindingSource.
                DataTable table = new DataTable
                {
                    Locale = CultureInfo.InvariantCulture
                };
                dataAdapter.Fill(table);
                bindingSource1.DataSource = table;

                // Resize the DataGridView columns to fit the newly loaded content.
                LogDataGridView.AutoResizeColumns(
                    DataGridViewAutoSizeColumnsMode.AllCellsExceptHeader);
            }
            catch (OleDbException)
            {

            }
        }
c# winforms datagridview
2个回答
1
投票

选项1:

如果存储状态信息的数据库没有被其他进程不断地更新,你可以简单地指定要加入的列是外部数据库中一个表的一部分。

如果它从其他来源接收更新,你就必须用Timer对它进行轮询(或者使用FileSystemWatcher类在数据库文件变化时接收通知)。不过,查询的方法是一样的。

添加 [;database=Second database Path].[Source Table] AS alias 子句后,然后照常进行。

例如,设置一个DataGridView.Datasource,指定第二个数据库路径。

LogDataGridView.DataSource = GetCrossJoinedTable([Second database path]);

连接字符串的 Data Source= 包含第一个数据库的路径。然后,使用一个共同的键交叉连接两个数据库中的两个Table,并返回包含第二个数据库中的Table的状态信息的列(the [Order Status] 列,如果我没有看错的话)。)

private DataTable GetCrossJoinedTable(string secondDataBasePath)
{
    var dt = new DataTable("JoinedTable");
    string sql = "SELECT [Data].*, status.[Order Status] " +
                $"FROM [Data] LEFT JOIN [;database={secondDataBasePath}].[Output] AS status " +
                 "ON [Data].[SO nr] = status.[Source No]";
    using (var connection = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=firstDatabase.accdb;Persist Security Info=false;"))
    using (var command = new OleDbCommand(sql, connection)) {
        connection.Open();
        var reader = command.ExecuteReader();
        dt.Load(reader);
        return dt;
    }
}

选项2: 查询第一个数据库,添加一个状态列,更新第二个数据库的状态信息,然后用定时器轮询新的状态信息。

你可以调用 LogDataGridView.DataSource = GetMainTableData() 来设置数据源。它还将从第二个数据库中加载状态信息。

然后,定时器将只轮询第二个数据库,以检查是否有足够的数据源。[Order Status] 匹配的 [SO nr] DataTable中的列发生了变化。当DataTable(在这里,一个名为的字段为 mainDT)更新,你的DataGraidView将立即反映出变化。

  • 如果数据可以被编辑,那么,如果 IsCurrentCellInEditMode 返回 true (请阅读这里关于CheckBoxColumns的说明),或者当一个Cell处于编辑模式时暂停(即CellBeginEdit 事件),并在单元格退出编辑模式时重新恢复(CellEndEdit 事件)。)
  • 记得在表格关闭时停止并处理定时器 (Form.FormClosing 事件)。)

如果你不需要Timer来轮询状态信息,只需调用 UpdateStatusInfo() 每当您需要更新DGV时。

System.Windows.Forms.Timer sqlTimer = null;
DataTable mainDT = new DataTable("MainTable");

private DataTable GetMainTableData()
{
    string sql = "SELECT * FROM Data";
    using (var connection = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=firstDatabase.accdb;Persist Security Info=false;"))
    using (var command = new OleDbCommand(sql, connection)) {
        connection.Open();
        var reader = command.ExecuteReader();
        mainDT.Load(reader);
        mainDT.Columns.Add(new DataColumn() {
            Caption = "Status", ColumnName = "fStatus", DataType = typeof(string), ReadOnly = true
        });
    }
    sqlTimer = new System.Windows.Forms.Timer() { Interval = 5000 };
    sqlTimer.Tick += (s, ev) => { UpdateStatusInfo(mainDT, false); };
    sqlTimer.Start();
    return UpdateStatusInfo(mainDT, true);
}

private DataTable UpdateStatusInfo(DataTable dt, bool returnTable)
{
    string sql = "SELECT Output.[Order Status], Output.[Source No] FROM Output";
    using (var connection = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=secondDatabase.accdb;Persist Security Info=false;"))
    using (var command = new OleDbCommand(sql, connection)) {
        connection.Open();
        var reader = command.ExecuteReader();
        dt.Columns["fStatus"].ReadOnly = false;
        while (reader.Read()) {
            dt.Select($"fNumber = {reader["Source No"]}").FirstOrDefault()?
              .SetField("fStatus", reader["Order Status"].ToString());
        }
        dt.Columns["fStatus"].ReadOnly = true;
        return returnTable ? dt : null;
    }
}

0
投票

你可以做什么?

1 从 OUTPUT 表中创建一个 DataTable 变量(例如 OutputDataTable)。

2 在您的方法中 private void GetData(string selectCommand)在设置数据源(bindingSource1.DataSource = table;),你可以描述一个事件RowsAdded ( dataGridView1.RowsAdded += this.DataGridView1_RowsAdded;).在你做的事情中,像 。

    private void DataGridView1_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
    {
        string valueToFind = dataGridView1[dataGridView1.Columns["SO nr"].Index, e.RowIndex].Value.ToString();
        var row = OutputDataTable.Select($"Source No" = '{valueToFind}'").First();
        string status = row["Order Status"].ToString();
        dataGridView1[dataGridView1[dataGridView1.Columns["Status"].Index, e.RowIndex].Value = status;
    }
© www.soinside.com 2019 - 2024. All rights reserved.