gpt4 book ai didi

winforms - 将 DataGridViewComboBoxCell 的数据源动态设置为基于其他单元格选择的过滤数据 View

转载 作者:行者123 更新时间:2023-12-04 22:14:56 56 4
gpt4 key购买 nike

我一直在上下寻找执行以下操作的方法,但无济于事。我提出了一个可行的解决方案,但想知道是否有更好的处理方法。

问题:

我正在使用具有两个 DataGridViewComboBoxColumn、col1 和 col2 的 DataGridView。

col1 已将其数据源设置为数据表。基于 col1 中给定单元格的选择,我希望同一行中的相应 col2 单元格将其数据源设置为 col2 的数据源的过滤 DataView。

我当前实现的缩写代码可能更好地帮助描述我正在尝试做的事情:

DataGridView dg = new DataGridView();
dg.DataSource = new BindingSource() { DataSource = _myDataTable }; //DataTable with Foreign Keys for ID1 and ID2
dg.CellValueChanged += new DataGridViewCellEventHandler(dg_CellValueChanged);
DataGridViewComboBoxColumn col1 = new DataGridViewComboBoxColumn();
col1.DataPropertyName = "ID1";
col1.DisplayMember = "Display1";
col1.ValueMember = "ID1";
col1.DataSource = dataTable1;
col1.ValueType = typeof(Int32);

DataGridViewComboBoxColumn col2 = new DataGridViewComboBoxColumn();
col2.DataPropertyName = "ID2";
col2.DisplayMember = "Display2";
col2.ValueMember = "ID2";
col2.DataSource = dataTable2;
col2.ValueType = typeof(Int32);

dg.Columns.Add(col1);
dg.Columns.Add(col2);

然后我将事件处理程序定义为:

private void dg_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex == 0 && e.RowIndex > -1)
{
var dgv = sender as DataGridView;
if (dgv == null)
return;

int selectedID;
if (!int.TryParse(dgv[e.ColumnIndex, e.RowIndex].Value.ToString(), out selectedID))
return;

var cell = dgv[e.ColumnIndex + 1, e.RowIndex] as DataGridViewComboBoxCell;
if (cell == null)
return;

var col = dgv.Columns[e.ColumnIndex + 1] as DataGridViewComboBoxColumn;
if(col == null)
return;

var dt = col.DataSource as DataTable; // The macro-DataTable containing all possible values
if(dt == null)
return;

DataView dv = new DataView(dt, "ID1 = " + selectedID, "DisplayOrder", DataViewRowState.CurrentRows);
if(dv.Count == 0)
return;

//This is the part that I am wondering if there is a better way of handling
cell.DataSource = dt; //Set the data source to the macro-DataTable so that when we set the Value to something in the new DataView it will not throw an exception
cell.DisplayMember = "Display2"; // Have to redefine the Display/Value members
cell.ValueMember = "ID2";
cell.Value = dv[0]["ID2"]; // Set the value to the first option in the new DataView to avoid an exception being thrown when setting the dv as the DataSource
cell.DataSource = dv;
}
}

最后一部分是我的担忧。动态切换cell2的DataSource时,如果cell2的当前选择没有出现在新的DataView中,则会抛出异常:

System.ArgumentException:DataGridViewComboBoxCell 值无效。

为了避免这种情况,我将数据源设置为宏数据表(包含可以根据 cell1 的选择显示的所有值),将 cell2 的选定值更改为 DataView 中的第一个结果,然后将 cell2 的 DataSource 设置为 DataView。这一切都确保单元格永远不会有无效的选择并且它按预期工作。

我的问题是,是否有更好/更简单的方法来做到这一点?对于我的使用,此代码仅在创建新行时激活,因此在给定表单中不会执行多次。但是,如果有更好的方法或一些改进的建议,我将不胜感激!

(这里是第一个问题,所以我也乐于接受关于发布的建议……对任何失误表示歉意)

编辑(提供表结构 - 还将“BoundID”更改为“ID1”以避免混淆):

DataGrid 的表结构为:

MainTableID int

ID1 int --This is a foreign key to col1

ID2 int --This is a foreign key to col2

第 1 列的表结构:

ID1 int

Display1 varchar(50)

第 2 列的表结构:

ID2 int

Display2 varchar(50)

ID1 int --This is a foreign key to col1

更新:我根据 Mohsen 的建议重新定义了 CellValueChanged 事件处理程序:

private void dg_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex == 0 && e.RowIndex > -1)
{
var dgv = sender as DataGridView;

var cell = dgv[e.ColumnIndex + 1, e.RowIndex] as DataGridViewComboBoxCell;
if (cell == null)
return;

DataView dv = new DataView( ((DataTable)((DataGridViewComboBoxColumn)dgv.Columns[e.ColumnIndex + 1]).DataSource), "ID1 = " + dgv.CurrentCell.Value, "DisplayOrder", DataViewRowState.CurrentRows);
if(dv.Count == 0)
return;

cell.DisplayMember = "Display2"; // Have to redefine the Display/Value members
cell.ValueMember = "ID2";
cell.DataSource = dv;
}
}

而且我已经按照他的建议为 DataError 添加了一个事件处理程序:

void dg_DataError(object sender, DataGridViewDataErrorEventArgs e)
{
if(e.ColumnIndex != 1)
{
//Alert the user for any other DataError's outside of the column I care about
MessageBox.Show("The following exception was encountered: " + e.Exception);
}
}

这似乎工作得很好。

最佳答案

您的代码可以简化为不抛出异常:

    if (e.ColumnIndex == 0 && e.RowIndex > -1)
{
var dgv = sender as DataGridView;

var cell = dgv[e.ColumnIndex + 1, e.RowIndex] as DataGridViewComboBoxCell;
if (cell == null)
return;

cell.DataSource = ((DataTable)((DataGridViewComboBoxColumn)dgv.Columns[e.ColumnIndex + 1]).DataSource).Select("BoundID = " + dgv.CurrentCell.Value);
}

已更新

当您更改第一个组合框中已设置的项目时,因为第二个组合框中的筛选数据 View 具有不同的 ID1,将引发异常“DataGridViewComboBoxCell 值无效。”。为了捕获此异常,在注册方法中没有代码的情况下注册 datagridview DataError 事件。然后,当您更改已经设置的组合框时,相应的组合框将填充正确的项目。

关于winforms - 将 DataGridViewComboBoxCell 的数据源动态设置为基于其他单元格选择的过滤数据 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13079070/

56 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com