除非按enter键,否则DataGridViewComboBoxColumn不会保存到数据源



我有一个DataGridView,它的DataSource属性绑定到DataTable。所述DataTable是手动填充的(不是从数据库中填充的(。我不会详细说明这到底是怎么发生的,因为除了我要描述的之外,一切都完美无瑕。一旦构建了DataTable,它就会使用以下代码绑定到DataGridView:

DgvResults.DataSource = _data.ResultsData;

此DataGridView的最后一列是使用以下代码创建的DataGridViewComboBoxColumn:

var col = new DataGridViewComboBoxColumn
{
Name = "newMedId",
HeaderText = @"Med ID (NEW PIS)",
DataPropertyName = "newMedId",
DisplayMember = "ItemId",
ValueMember = "ItemId",
ReadOnly = false,
Resizable = DataGridViewTriState.False,
SortMode = DataGridViewColumnSortMode.Programmatic
};
col.Items.Add("");
col.Items.Add("DELETE");
_data.NewFormularyData.AsEnumerable().Select(r => r.Field<string>("ItemId")).ToList()
.ForEach(m => col.Items.Add(m));
DgvResults.Columns.Add(col);

这基本上是用来自另一个DataTable的所有ID填充该列中的每个ComboBox;删除";值位于顶部。

我还对这个DataGridView进行了自定义编程排序。我不会发布代码,因为我认为它不相关,但本质上它是通过ColumnHeaderMouseClick事件触发的,只需根据单击的列对底层DataTable进行排序,取消DataGridView的DataSource属性并重新绑定它。

除此之外,这一切都很好:假设DataGridViewComboBoxColumn中的一个下拉列表为空,然后我手动将值更新为其他值。如果在选择所述值后立即对DataGridView进行排序,则该值不会更新基础DataTable,并且会丢失。如果我做了同样的事情,但在选择值后按下了回车键,它会正确更新。

我的应用程序有一个功能,可以将上述DataTable导出到Excel电子表格中。单击该按钮会导致电子表格中包含我更新的值,即使我在选择该按钮后没有点击回车键。它的行为就像DataGridViewComboBoxCell在更新其绑定的DataTable之前需要失去焦点一样。立即单击列标题对其进行排序似乎不会提供这种失去焦点的情况,并且该值也不会更新。

如何在DataTable中立即更新此值?

这是一个再现问题的MRE/strong>

using System;
using System.ComponentModel;
using System.Data;
using System.Windows.Forms;
namespace MRE
{
public partial class Form1 : Form
{
private DataTable dt;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
SetupDgv();
CreateDT();
Dgv.DataSource = dt;
}
private void CreateDT()
{
dt = new DataTable();
dt.Columns.Add("test1", typeof(string));
dt.Columns[0].ColumnName = "test1";
dt.Columns[0].Caption = "test1";
dt.Columns.Add("test2", typeof(string));
dt.Columns[1].ColumnName = "test2";
dt.Columns[1].Caption = "test2";
var row = dt.NewRow();
row[0] = 1;
row[1] = 1;
dt.Rows.Add(row);
row = dt.NewRow();
row[0] = 2;
row[1] = 2;
dt.Rows.Add(row);
row = dt.NewRow();
row[0] = 3;
row[1] = 3;
dt.Rows.Add(row);
}
private void SetupDgv()
{
Dgv.Columns.Add("test1", "test1");
Dgv.Columns[0].DataPropertyName = "test1";
Dgv.Columns[0].ReadOnly = true;
Dgv.Columns[0].Resizable = DataGridViewTriState.False;
Dgv.Columns[0].SortMode = DataGridViewColumnSortMode.Programmatic;
var col = new DataGridViewComboBoxColumn
{
Name = "test2",
HeaderText = "test2",
DataPropertyName = "test2",
ReadOnly = false,
Resizable = DataGridViewTriState.False,
SortMode = DataGridViewColumnSortMode.Programmatic
};
col.Items.Add("");
col.Items.Add("DELETE");
col.Items.Add("1");
col.Items.Add("2");
col.Items.Add("3");
Dgv.Columns.Add(col);
}
private void Dgv_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
var newColumn = Dgv.Columns[e.ColumnIndex];
var oldColumn = Dgv.GetSortedColumnFromDataTable(dt);
ListSortDirection direction;
if (oldColumn != null)
{
if (oldColumn == newColumn && dt.GetDataTableSortOrder() == "ASC")
direction = ListSortDirection.Descending;
else
{
direction = ListSortDirection.Ascending;
oldColumn.HeaderCell.SortGlyphDirection = SortOrder.None;
}
}
else
direction = ListSortDirection.Ascending;
Dgv.ClearSortGlyphInAllColumnsExcept(e.ColumnIndex);
dt.DefaultView.Sort = direction == ListSortDirection.Ascending ?
Dgv.Columns[e.ColumnIndex].Name + " ASC" : Dgv.Columns[e.ColumnIndex].Name + " DESC";
newColumn.HeaderCell.SortGlyphDirection =
direction == ListSortDirection.Ascending ? SortOrder.Ascending : SortOrder.Descending;
}
}
public static class DGVExtensions
{
public static DataGridViewColumn GetSortedColumnFromDataTable(this DataGridView dgv, DataTable dt)
{
var dtSort = dt.DefaultView.Sort;
string colName;
if (dtSort.IndexOf(" ") != -1)
colName = dtSort.Substring(0, dtSort.IndexOf(" "));
else
colName = dtSort;
return dgv.Columns[colName];
}
public static void ClearSortGlyphInAllColumnsExcept(this DataGridView dgv, int index)
{
foreach (DataGridViewColumn col in dgv.Columns)
{
if (col.Index != index)
col.HeaderCell.SortGlyphDirection = SortOrder.None;
}
}
}
public static class DTExtensions
{
public static string GetDataTableSortOrder(this DataTable dt)
{
if (dt.DefaultView.Sort.IndexOf(" ") == -1)
return "ASC";
else
{
var startIndex = dt.DefaultView.Sort.IndexOf(" ") + 1;
return dt.DefaultView.Sort.Substring(startIndex, dt.DefaultView.Sort.Length - startIndex).ToUpper();
}
}
}
}

Dgv_ColumnHeaderMouseClick事件中,添加以下代码行作为事件中的第一行代码。。。

Dgv.CommitEdit(DataGridViewDataErrorContexts.Commit);

最新更新