【问题标题】:C# & SQL : how to update table without refreshing DataGridView?C# & SQL:如何在不刷新 DataGridView 的情况下更新表?
【发布时间】:2015-10-16 06:00:23
【问题描述】:

我总是用

DataGridView.DataSource = (DataTable)tbl; 

但是这种方法完全刷新了 Datagridview,比如 selectedrows、滚动条位置、backColor 等。我只想从 SQL 更新单元格数据,而没有完整的 datagridview 刷新

例如 uTorrent 有一个类似 datagridview 的表格,在某些单元格中 x KB/s 的值总是在刷新,但 torrentdatagrid 是静态的。没有滚动移动,没有选择消失等。

你能帮我做这件事吗?

对不起,我的英语不好。谢谢。

【问题讨论】:

  • 当然,您可以迭代行和列并设置新值。但是为什么不只保存datagridview的选定索引,设置数据源后重新选择呢?
  • #Reza Aghaei,因为如果我按照你说的那样做,屏幕上会发生一些动作,比如(在数据源刷新后:) 滚动到表的顶部,并且当重新选择时,执行滚动位置再次发生变化。当这些很开心时,用户会看到所有的操作。我想,是的,它会起作用,但这是一件坏事。
  • 如果从数据源中删除或添加了一些记录怎么办?
  • 我只会更新数据。如果删除或添加(插入)一些数据,我必须更改数据源。我的问题仅用于更新数据。逐行迭代方法是唯一的解决方案吗?
  • 你的表有主键吗?

标签: c# datagridview sql-update


【解决方案1】:

如果您的表有一个主键,并且您只想更新现有/添加新行,您可以像这样使用DataTable.Merge Method

最初

dataGridView.DataSource = initial_data_table;

更新

((DataTable)dataGridView.DataSource).Merge(new_data_table);

更新: 上述方法是最简单的,但正如 cmets 中所述,由于 Merge 方法优化会抑制操作期间的更改通知并引发 @987654326 @ 事件以ListChangedType.Reset 结尾。所以,这里有一个简单有效的方法,基于DataTable.LoadDataRow Method

foreach (var dataRow in newTable.AsEnumerable())
    table.LoadDataRow(dataRow.ItemArray, LoadOption.OverwriteChanges);

还有一个样本证明:

using System;
using System.Data;
using System.Linq;
using System.Windows.Forms;

namespace Samples
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            var form = new Form();
            var dg = new DataGridView { Dock = DockStyle.Fill, Parent = form };
            var data = GetData();
            dg.DataSource = data;
            var updateTimer = new Timer { Interval = 200, Enabled = true };
            updateTimer.Tick += (sender, e) =>
            {
                foreach (var dr in GetData().AsEnumerable())
                    data.LoadDataRow(dr.ItemArray, LoadOption.OverwriteChanges);
            };
            Application.Run(form);
        }
        static DataTable GetData()
        {
            var dt = new DataTable();
            dt.Columns.Add("Id", typeof(int));
            dt.Columns.Add("Name");
            dt.Columns.Add("Score", typeof(int));
            dt.PrimaryKey = new[] { dt.Columns["Id"] };
            var random = new Random();
            for (int i = 1; i <= 1000; i++)
                dt.Rows.Add(i, "Player #" + i, random.Next(1, 100000));
            return dt;
        }
    }
}

【讨论】:

  • 重置网格滚动位置和选择的记录。它刷新了网格。
  • @RezaAghaei 我的测试表明只有水平滚动位置被重置。垂直滚动位置和所选记录不受影响。
  • 我不知道刷新网格是什么意思 - 需要更新网格,这是迄今为止最简单的方法,除了水平滚动条,我没有看到其他副作用。
  • @IvanStoev 我又试了一次,不幸的是它的行为就像你设置网格的数据源时一样。它改变了滚动和选定记录的位置。
  • @IvanStoev 我认为最好的工作想法是使用循环更新第一个 dataTable 的单元格。我使用循环更新了 dataGridView 单元格,但最好更新第一个 dataTable,并且由于 dataTable 支持 2 路数据绑定,更新将显示在 dataGridView 中,而无需更改滚动位置和选定的行。
【解决方案2】:

也许我很难解释问题。对不起。但是,这段代码解决了我的问题,

            for (int i = 0; i < dg.Rows.Count; i++)
            {
                for (int j = 1; j < dg.Columns.Count ; j++)
                {
                    dg.Rows[i].Cells[j].Value = NewDataTable.Select("ID=" + dg.Rows[i].Cells[0].Value)[0][j].ToString();
                }
            }

第一列是 ID 主键列。我通过计时器更新并实时将数据传递到我的datagridview。谢谢

【讨论】:

  • 这和我的代码一样,你用的是简单的 for 循环,而我用的是 linq。
  • 是的。我不擅长 Linq。但我也试过你的代码。我可以得到结果。但是非常感谢礼萨
  • 这个解决方案会出现只读列的问题,也会出现重新排序的列的问题,当表格的列不存在于网格中时也会出现问题,而我的帖子涵盖了这些问题。
  • 值得一提的是它也非常低效。
猜你喜欢
  • 1970-01-01
  • 2022-01-21
  • 2011-06-15
  • 2019-11-25
  • 1970-01-01
  • 1970-01-01
  • 2017-03-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多