C# C&SQL:如何在不刷新DataGridView的情况下更新表?

C# C&SQL:如何在不刷新DataGridView的情况下更新表?,c#,datagridview,sql-update,C#,Datagridview,Sql Update,我总是用 DataGridView.DataSource = (DataTable)tbl; 但是这个方法完全重新设计了Datagridview,比如selectedrows、滚动条位置、背景色等等。。我只想在没有完全datagridview刷新的情况下从SQL更新单元格数据 例如,uTorrent有一个类似datagridview的表,在某些单元格中,x KB/s的值总是重新定义,但torrentdatagrid是静态的。没有滚动,没有选择消失等 你能帮我做这个吗 我很抱歉我的英语不好。谢

我总是用

DataGridView.DataSource = (DataTable)tbl; 
但是这个方法完全重新设计了Datagridview,比如selectedrows、滚动条位置、背景色等等。。我只想在没有完全datagridview刷新的情况下从SQL更新单元格数据

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

你能帮我做这个吗


我很抱歉我的英语不好。谢谢。

如果您的表有主键,并且您只想更新现有行/添加新行,则可以这样使用:

最初

dataGridView.DataSource = initial_data_table;
更新

((DataTable)dataGridView.DataSource).Merge(new_data_table);
更新:上面的方法是最简单的,但正如注释中所提到的,它有副作用,因为合并方法优化会在操作期间抑制更改通知,并在最后使用ListChangedType.Reset引发ListChanged事件。因此,这里有一个简单而有效的方法,它基于:

以及一个样本,证明:

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;
        }
    }
}

也许我会努力解释这个问题。对不起。但是这个代码解决了我的问题

            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。谢谢

您当然可以对行和列进行迭代并设置新值。但为什么不保存datagridview的选定索引,并在设置datasource后重新选择它呢?Reza Aghaei,因为如果我按照您所说的那样做,屏幕上会出现一些操作,比如在datasource刷新后:scroll将位于表的顶部,并且当重新选择执行sroll位置再次更改时。当这些发生时,用户可以看到所有的动作。我想,是的,它会工作,但这是一件坏事。所以,如果一些记录从数据源中删除或添加到数据源中呢?我只会更新数据。如果删除或添加了一些数据,我必须更改数据源。我的问题只是更新数据。逐行迭代法是唯一的解决方案吗?您的表有主键吗?它重置网格滚动位置和所选记录。它刷新网格。@RezaAghaei我的测试显示只有水平滚动位置被重置。垂直滚动位置和所选记录不受影响。我不知道刷新网格是什么意思-网格需要更新,这是迄今为止最简单的方法,除了水平滚动条,我看不到其他副作用。@IvanStoev我再试了一次,不幸的是,它的行为与设置网格数据源时的行为类似。它会改变滚动条和所选记录的位置。@IvanStoev我认为最好的工作方法是使用循环更新第一个数据表的单元格。我使用循环更新了dataGridView单元格,但最好更新第一个dataTable,因为dataTable支持双向数据绑定,更新将显示在dataGridView中,而不更改滚动位置和所选行。这与我的代码相同,在我使用linq.Yes时,您使用simple for loops。我不擅长林克。但我也试过你的代码。我会得到结果的。但是thaks Reza这么多这个解决方案在只读列方面会有问题,在重新排序的列方面也会有问题,在网格中不存在表的列时也会有问题,而我的文章讨论了这些问题。值得一提的是,它的效率也很低。
            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();
                }
            }