【问题标题】:DataGridview with BindingSource as DataSource displays values only after selecting a Row以 BindingSource 作为 DataSource 的 DataGridview 仅在选择 Row 后才显示值
【发布时间】:2020-09-25 17:07:38
【问题描述】:

我正在使用 DataGridView 来显示字符串值,它使用字符串包装类、BindingSource 和 BindingList。
但是,在启动应用程序时,这些值仅在单击行后才可见。我已经尝试查看所有可能的样式属性以查看初始黑色的来源,但没有成功。

初步外观:

点击后(有趣的颜色试图了解哪种样式做了什么)或最小化和最大化窗口:

表单代码(这里已经尝试过一些变种,最终版本不会是这样的):

private BindingSource dataSource;
private BindingList<StringValue> bindingList;
private List<StringValue> list = new List<StringValue>();

public MainForm()
{
    InitializeComponent();

    grdCodes.AutoGenerateColumns = false;

    bindingList = new BindingList<StringValue>(list);
    dataSource = new BindingSource(bindingList, null);
    grdCodes.DataSource = dataSource;

    // Load += MainForm_Load;
    x();
}

//private void MainForm_Load(object sender, EventArgs e)
//{
//    grdSupiCodes.AutoGenerateColumns = false;

//    bindingList = new BindingList<StringValue>(list);
//    dataSource  = new BindingSource(bindingList, null);
//    grdSupiCodes.DataSource = dataSource;
//}

private void x()
{
    list.Add(new StringValue("AAAAAAAAAAAA"));
    list.Add(new StringValue("BBBBBBBBBBBB"));
    list.Add(new StringValue("CCCCCCCCCCCC"));

    // none of the below work:
    grdCodes.ResetBindings();

    // grdCodes.Update();
    // grdCodes.Refresh();

    // grdCodes.DataSource = null;
    // grdCodes.DataSource = dataSource;
}

我的问题是,如何让应用启动时已经在网格中显示值?如果有帮助,我可以发布设计器代码,但没有定义黑色(表单背景为 DarkGrey,在网格下可见)。

【问题讨论】:

  • 在构造函数中,在创建BindingList 之前添加list 项。所以将x(); 方法向上移动。
  • @dr.null 这不起作用。当我移动它们出现的窗口时,这些值在那里但不可见。这是一些晦涩难懂的重绘问题。

标签: c# winforms datagridview bindingsource bindinglist


【解决方案1】:

鉴于所描述的场景:

  1. 将一个空的List&lt;class&gt;INotifyPropertyChanged 很可能未实现)添加到相同类型的 BindingList。
  2. 空的BindingList 设置为BindingSource 的DataSource。
  3. BindingSource(绑定到仍然为空的 BindingList)设置为 DataGridView 的 DataSource

之后会向列表中添加一些新项目。
在这种情况下,很容易验证 BindingSource 没有收到任何订阅事件的 ListChanged 事件:该事件永远不会引发。

  • 即使 Bindinglist.Count 属性递增到添加的项目数,此计数也仅报告源 List&lt;class&gt; 中包含的项目数,不会通知更改。
    DataGridView实际上可以显示新的内容,但是底层的DataSource——BindingSource生成的内部List——与原始源断开:当在DataGridView中选择了一个Row时,最常见的结果是引发了 IndexOutOfRangeException,因为我们正在尝试从内部字典访问非同步项目,实际上是访问索引 -1 处的项目。

可以使用几种方法来同步内部集合:

  1. 将新项目直接添加到 BindingList 而不是源 List&lt;class&gt;:BindingList 将在链接的 BindingSource 中生成 ListChanged 事件,同步集合和源 List&lt;class&gt; 无论如何都会更新。

     bindingList.Add(new StringValue("StringValue1"));
     bindingList.Add(new StringValue("StringValue2"));
     bindingList.Add(new StringValue("StringValue3"));
    
  2. 如果需要在原来的List&lt;class&gt;中添加新的Item,由于某种原因,在添加新的Item之后调用BindingList.ResetBinding()BindingSource.ResetBinding(false)方法;这将生成ListChanged 事件并因此执行同步:

     list.Add(new StringValue("StringValue1"));
     list.Add(new StringValue("StringValue2"));
     list.Add(new StringValue("StringValue3"));
     bindingList.ResetBindings();
     // Or...
     // bindingSource.ResetBinding(false);
    
  3. 我们可以将DataSource设置为相应的Type,而不是直接使用BindingList&lt;class&gt;对象作为BindingSource的DataSource,这样DataGridView将使用DataPropertyName属性将其Columns绑定到数据源,如果@ 987654344@,或从源对象属性名称生成列,当AutoGenerateColumns = true

     BindingList bindingList = new BindingList<StringValue>(list);
     BindingSource bindingSource = new BindingSource(typeof(BindingList<StringValue>), null);
     dataGridView.DataSource = bindingSource;
    

    将新Item添加到源List&lt;class&gt;后,将BindingSource的DataSource设置为BindingList,导致内部集合重新同步:

     list.Add(new StringValue("StringValue1"));
     list.Add(new StringValue("StringValue2"));
     list.Add(new StringValue("StringValue3"));
     bindingSource.DataSource = bindingList;
    

【讨论】:

    猜你喜欢
    • 2016-09-03
    • 2020-07-02
    • 1970-01-01
    • 1970-01-01
    • 2017-04-08
    • 1970-01-01
    • 2010-11-23
    • 2010-12-12
    • 2013-07-29
    相关资源
    最近更新 更多