【问题标题】:Refresh DataGridView when updating data source更新数据源时刷新 DataGridView
【发布时间】:2010-09-20 05:03:27
【问题描述】:

当您更新基础数据源时,刷新DataGridView 的最佳方式是什么?

我经常更新数据源,并希望在结果发生时向用户显示结果。

我有类似的东西(它有效),但将DataGridView.DataSource 设置为null 似乎不是正确的方法。

List<ItemState> itemStates = new List<ItemState>();
dataGridView1.DataSource = itemStates;

for (int i = 0; i < 10; i++) { 
    itemStates.Add(new ItemState { Id = i.ToString() });
    dataGridView1.DataSource = null;
    dataGridView1.DataSource = itemStates;
    System.Threading.Thread.Sleep(500);
}

【问题讨论】:

  • 你能看看我的answer,如果最合适的话,可以接受吗?

标签: c# .net winforms datagridview


【解决方案1】:

试试这个代码

List itemStates = new List();

for (int i = 0; i < 10; i++)
{ 
    itemStates.Add(new ItemState { Id = i.ToString() });
    dataGridView1.DataSource = itemStates;
    dataGridView1.DataBind();
    System.Threading.Thread.Sleep(500);
}

【讨论】:

  • DataBind() 是一种用于数据绑定控件的 ASP .Net 方法。
【解决方案2】:

嗯,没有比这更好的了。正式来说,你应该使用

dataGridView1.DataSource = typeof(List); 
dataGridView1.DataSource = itemStates;

它仍然是一种“清除/重置源”类型的解决方案,但我还没有找到可以可靠地刷新 DGV 数据源的任何其他解决方案。

【讨论】:

  • 用'typeof(List)'代替null有什么意义?
  • @GWLlosa,如果您使用自动生成的列并将数据源设置为 NULL,它将清除这些列。通过使用 typeof(List) 它应该在刷新期间保持列结构。我个人会使用 AutoGenerateColumns = false;并在刷新的第一遍创建列。这样,如果用户调整列的大小,它不会在刷新时丢弃他们的更改。
  • @Alan 为什么不使用 BindingSource,然后您可以刷新干净整洁的内容,而不是像以前那样重新绑定?
  • @CodeBlend - 好吧,如果你的意思是 BindingSource.ResetBindings(),它只是不会为我刷新项目。 DataSource 属性需要“清除”并再次设置以查看任何更改。非常感谢 BindingSource 的工作示例 ;)
  • dataGridView1.DataSource 设置为新数据有什么问题。即使AutoGenerateColumns 为真,这也会自动更新网格而不删除列的结构。
【解决方案3】:

我自己也遇到过这个。我的建议:如果您拥有数据源的所有权,请不要使用List。使用BindingListBindingList 具有在添加或更改项目时触发的事件,DataGridView 将在触发这些事件时自动更新自身。

【讨论】:

  • 这是个好建议。之后,您只需调用 .Refresh() 即可让 datagridview 刷新其显示的数据...
  • 可以逐行刷新使用:bindingList.ResetItem(bindingList.IndexOf(item));
  • .Refresh() 只是谈论控件重绘,与绑定无关,除非我错了! “强制控件使其客户区无效并立即重绘自身和任何子控件。” Control.Refresh Method
  • BindingListBindingSource 并使用 ResetBindings 对我不起作用。
【解决方案4】:

这是从THIS 地方复制我的答案。

只需要像这样再次填充数据网格:

this.XXXTableAdapter.Fill(this.DataSet.XXX);

如果您使用从 dataGridView 自动连接,此代码将在 Form_Load() 中自动创建

【讨论】:

    【解决方案5】:

    Observablecollection:表示提供通知的动态数据集合 添加、删除项目或刷新整个列表时。 您可以枚举实现 IEnumerable 接口的任何集合。 但是,要设置动态绑定,以便在 集合自动更新 UI, 集合必须实现 INotifyCollectionChanged 接口。 此接口公开 CollectionChanged 事件, 每当基础集合更改时应引发的事件。

    Observablecollection<ItemState> itemStates = new Observablecollection<ItemState>();
    
    for (int i = 0; i < 10; i++) { 
        itemStates.Add(new ItemState { Id = i.ToString() });
      }
     dataGridView1.DataSource = itemStates;
    

    【讨论】:

      【解决方案6】:

      您正在循环内设置数据源,并在每次添加后休眠 500。为什么不直接添加到 itemstates 中,然后在添加完所有内容后设置数据源。如果你想让线程在那之后休眠。这里的第一个代码块是我修改的第二个代码块。

      for (int i = 0; i < 10; i++) { 
          itemStates.Add(new ItemState { Id = i.ToString() });
          dataGridView1.DataSource = null;
          dataGridView1.DataSource = itemStates;
          System.Threading.Thread.Sleep(500);
      }
      

      如下更改您的代码:这要快得多。

      for (int i = 0; i < 10; i++) { 
          itemStates.Add(new ItemState { Id = i.ToString() });
      
      }
          dataGridView1.DataSource = typeof(List); 
          dataGridView1.DataSource = itemStates;
          System.Threading.Thread.Sleep(500);
      

      【讨论】:

        【解决方案7】:

        在这种情况下,最简洁、最有效和范式友好的解决方案是使用System.Windows.Forms.BindingSource 作为您的项目列表(数据源)和您的DataGridView 之间的代理:

        var itemStates = new List<ItemState>();
        var bindingSource1 = new System.Windows.Forms.BindingSource { DataSource = itemStates };
        dataGridView1.DataSource = bindingSource1;
        

        然后,在添加项目时,使用BindingSourceAdd() 方法而不是列表的Add() 方法:

        for (var i = 0; i < 10; i++)
        {
            bindingSource1.Add(new ItemState { Id = i.ToString() });
            System.Threading.Thread.Sleep(500);
        }
        

        通过这种方式,您可以将项目添加到列表中,并使用同一行代码通知 DataGridView 这些添加。每次更改列表时都无需重置DataGridViewDataSource

        还值得一提的是,您可以直接在 Visual Studio 的表单设计器中将 BindingSource 拖放到表单上,并将其作为数据源附加到您的 DataGridView 那里,这样可以为您节省上面的一行代码我手动执行的示例。

        【讨论】:

        • 这个答案应该已经收到正确的答案标志。我的投票在这里。
        • @jsa:不幸的是,OP 自 2009 年以来就没有访问过 SO。
        • 绝对是最好的答案 - 可惜对方得到了这么多赞成票,但收集它们的时间要长得多,按日期来判断!
        • 很好的解决方案,bindingsource[e.RowIndex]=mylist; 非常适合我,而不是 datagridview.Refresh(); 谢谢@Alexander
        猜你喜欢
        • 2017-05-27
        • 1970-01-01
        • 1970-01-01
        • 2012-12-24
        • 2013-08-30
        • 1970-01-01
        • 2012-04-25
        • 1970-01-01
        相关资源
        最近更新 更多