C# 以编程方式将单元格和行添加到DataGridView

C# 以编程方式将单元格和行添加到DataGridView,c#,winforms,datagridview,datagridviewcombobox,datagridviewcomboboxcell,C#,Winforms,Datagridview,Datagridviewcombobox,Datagridviewcomboboxcell,我正在努力处理DataGridViewComboxCell。在某些情况下(比如事件),我必须在表单的DataGridView中预先选择ComboBox的值。当用户更改一个框时,我可以通过编程方式更改另一个框,如下所示: var item = ItemName.Items.GetListItem(name); if (item != null) { _loading = true; // that's needed to come around another CellValueChang

我正在努力处理
DataGridViewComboxCell
。在某些情况下(比如事件),我必须在表单的
DataGridView
中预先选择
ComboBox
的值。当用户更改一个框时,我可以通过编程方式更改另一个框,如下所示:

var item = ItemName.Items.GetListItem(name);
if (item != null)
{
    _loading = true; // that's needed to come around another CellValueChanged events
    itemView.Rows[e.RowIndex].Cells["ItemName"].Value = item;
    _loading = false;
}
foreach (var item in _model.DefaultData.ItemList)
{
    if (item.Value.Code.HasValue()) ItemCode.Items.Add(new ListItem(item.Key, item.Value.Code));
    ItemName.Items.Add(new ListItem(item.Key, item.Value.Name));
}
我正在填充
ItemName.Items
如下:

var item = ItemName.Items.GetListItem(name);
if (item != null)
{
    _loading = true; // that's needed to come around another CellValueChanged events
    itemView.Rows[e.RowIndex].Cells["ItemName"].Value = item;
    _loading = false;
}
foreach (var item in _model.DefaultData.ItemList)
{
    if (item.Value.Code.HasValue()) ItemCode.Items.Add(new ListItem(item.Key, item.Value.Code));
    ItemName.Items.Add(new ListItem(item.Key, item.Value.Name));
}
GetListItem方法:

public static ListItem GetListItem(this DataGridViewComboBoxCell.ObjectCollection col, string name)
{
    ListItem retItem = null;
    foreach (ListItem item in col)
    {
        if (item.Name == name) { retItem = item; break; }
    }
    return retItem;
}
那很好,但是

现在我想在表单加载时向
DataGridView
添加行,如下所示:

foreach (var item in _model.SelectedItems)
{
    var row = new DataGridViewRow();
    row.Cells.Add(new DataGridViewTextBoxCell { Value = item.Id });
    row.Cells.Add(new DataGridViewComboBoxCell { Value = ItemCode.Items.GetListItem(item.Code) });
    row.Cells.Add(new DataGridViewComboBoxCell { Value = ItemName.Items.GetListItem(item.Name) });
    row.Cells.Add(new DataGridViewTextBoxCell { Value = item.Units });
    ...
    itemView.Rows.Add(row);
}
而抛出的
DataGridViewComboBox值无效
异常。请帮帮我,我想不起来了。我不想使用
DataSource
之类的东西
ItemCode
ItemName
列项目通过
GetListItem()
正确填充和返回。我不明白为什么它正常工作,但在表单加载时它不工作(在显示的屏幕上它也不工作)

编辑:对不起,忘记添加了

我的ListItem类:

public class ListItem
{
    public int Id { get; set; }
    public string Name { get; set; }
    public ListItem(int sid, string sname)
    {
        Id = sid;
        Name = sname;
    }
    public override string ToString()
    {
        return Name;
    }
}
我已经在表单加载中添加了:

ItemName.ValueMember = "Id";
ItemName.DisplayMember = "Name";
ItemCode.ValueMember = "Id";
ItemCode.DisplayMember = "Name";

好的,我自己解决了

显然,
datagridviewcomboxcolumn.Items
包含可能的项是不够的。如果要以编程方式添加新行,还必须将项目添加到
DataGridViewComboxCell.items

因此,如果其他人尝试使用我的方法不使用数据绑定,如
DataTable
等,我的解决方案如下:

foreach (var item in _model.SelectedItems)
{
    var row = new DataGridViewRow();
    var codeCell = new DataGridViewComboBoxCell();
    codeCell.Items.AddRange(ItemCode.Items);
    codeCell.Value = ItemCode.Items.GetListItem(item.Code);
    var nameCell = new DataGridViewComboBoxCell();
    nameCell.Items.AddRange(ItemName.Items);
    nameCell.Value = ItemName.Items.GetListItem(item.Name);
    row.Cells.Add(new DataGridViewTextBoxCell { Value = item.Id });
    row.Cells.Add(codeCell);
    row.Cells.Add(nameCell);
    row.Cells.Add(new DataGridViewTextBoxCell { Value = item.Units });
    row.Cells.Add(new DataGridViewTextBoxCell { Value = item.Quantity });
    row.Cells.Add(new DataGridViewTextBoxCell { Value = item.PriceLt });
    row.Cells.Add(new DataGridViewTextBoxCell { Value = item.PriceEu });
    itemView.Rows.Add(row);
}
DataGridViewColumn[]dgCol=
{
新的DataGridViewTextBoxColumn()
{
HeaderText=“定罪”,
SortMode=DataGridViewColumnSortMode.NotSortable,
宽度=转换为32(0.25f*grdConvictions.Width-19)
},
新的DataGridViewTextBoxColumn()
{
HeaderText=“积分”,
SortMode=DataGridViewColumnSortMode.NotSortable,
宽度=转换为32(0.125f*grdConvictions.Width-19)
},
新的DataGridViewTextBoxColumn()
{
HeaderText=“日期”,
SortMode=DataGridViewColumnSortMode.NotSortable,
宽度=转换为32(0.125f*grdConvictions.Width-19),
},
新的DataGridViewComboxColumn()
{
HeaderText=“Galletas”,
宽度=转换为32(0.25*GRD约束宽度-19),
DataPropertyName=“Galletas”,
数据源=新列表{“”,
“Maiz”,
“佩拉”,
“曼扎纳”,
“桑迪亚”,
“弗雷萨”,
“甜瓜”,
“梅洛克顿”,
“马拉库亚”,
“塞雷扎”,
“Frambuesa”,
“莫拉”,
“猕猴桃”,
“Anona”,
“瓜亚巴”
},
SortMode=DataGridViewColumnSortMode.NotSortable,
MaxDropDownItems=10,
DisplayStyle=DataGridViewComboxDisplayStyle.Nothing,
只读=假
}
};

YourDataGridView.Columns.AddRange(dgCol)

注意:DisplayStyle=DataGridViewComboxDisplayStyle.ComboBox以查看组合。我用“没什么”和…:

private void grdConvictions\u cellnenter(对象发送方,DataGridViewCellEventArgs e)
{
int colIndex=e.ColumnIndex;
int rowIndex=e.rowIndex;
如果(行索引<0 | | colIndex<0)
{
返回;
}
DataGridView grd=(DataGridView)发送方;
if(grd[e.ColumnIndex,e.RowIndex].GetType().Name!=“DataGridViewComboxCell”)
{
((DataGridViewComboxCell)grd.CurrentCell).DisplayStyle=DataGridViewComboxDisplayStyle.DropDownButton;
}
}

private void grdConvictions\u CellLeave(对象发送方,DataGridViewCellEventArgs e)
{
int colIndex=e.ColumnIndex;
int rowIndex=e.rowIndex;
如果(行索引<0 | | colIndex<0)
{
返回;
}
DataGridView grd=(DataGridView)发送方;
if(grd[e.ColumnIndex,e.RowIndex].GetType().Name!=“DataGridViewComboxCell”)
{
((DataGridViewComboxCell)grd.CurrentCell).DisplayStyle=DataGridViewComboxDisplayStyle.Nothing;
}
}

你说的“我不想使用数据源或类似的东西”是什么意思?如果您没有设置项目,
组合框如何知道要选择的项目?它将只知道当前选定的值。另外,请确保手动添加的单元格与DataGrid列的顺序正确。我通过
ItemName.items向
ComboBox
添加项目。添加(…)
其中
ItemName
ComboBox
。就像我说的,当我改变网格单元格的值时,它就起作用了,但当我以编程方式加载行时,它就不起作用了。您已经发布了很多代码片段,但是很难将它们关联起来,我相信其中有一半与问题无关。试着去创造。从一个新项目开始,这个项目只有datagrid和combobox列,并在load事件中添加虚拟项。如果成功,则包括cellchanged事件。增量增加代码并测试问题,直到它出现在最短的自包含示例中。然后你要么理解问题,要么至少找出问题所在,让其他人来解决。好的,我会尽我最大的努力。。。
    private void grdConvictions_CellLeave(object sender, DataGridViewCellEventArgs e)
    {
        int colIndex = e.ColumnIndex;
        int rowIndex = e.RowIndex;

        if (rowIndex < 0 || colIndex < 0)
        {
            return;
        }

        DataGridView grd = (DataGridView)sender;

        if (grd[e.ColumnIndex, e.RowIndex].GetType().Name != "DataGridViewComboBoxCell")
        {
            ((DataGridViewComboBoxCell)grd.CurrentCell).DisplayStyle = DataGridViewComboBoxDisplayStyle.Nothing;
        }

    }