以 BindingSource 作为 DataSource 的 DataGridview 仅在选择行后显示值

DataGridview with BindingSource as DataSource displays values only after selecting a Row

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

初看:

单击(有趣的颜色以尝试了解哪种样式的作用)或最小化和最大化 window:

表单代码(已经在这里尝试了一些变体,最终版本不会像这样):

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

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

鉴于所描述的场景:

  1. 将空 List<class>INotifyPropertyChanged 很可能未实现)添加到相同类型的 BindingList。
  2. BindingList is set as the DataSource of a BindingSource.
  3. BindingSource(绑定到仍为空的 BindingList)被设置为 DataGridView 的 DataSource

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

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

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

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

     bindingList.Add(new StringValue("StringValue1"));
     bindingList.Add(new StringValue("StringValue2"));
     bindingList.Add(new StringValue("StringValue3"));
    
  2. 如果原来的List<class>需要添加新的Items,由于某些原因,在添加新的Items后调用BindingList.ResetBinding() or the 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. 与其直接使用BindingList<class>对象作为BindingSource的DataSource,我们可以将DataSource设置为相应的Type,这样DataGridView会将其Columns绑定到数据源使用DataPropertyName 属性,如果 AutoGenerateColumns = false,或者从源对象属性名称生成列,当 AutoGenerateColumns = true:

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

    新的Item添加到源List<class>后,设置BindingSource的DataSource为BindingList,导致内部集合re-synchronize:

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