如何使用C#根据对象值查找行的索引

本文关键字:查找 索引 对象 何使用 | 更新日期: 2023-09-27 17:59:15

我有一个datagridview,我想从中删除一个特定的行(datagridview不是数据绑定的)。要删除,我需要该行的索引。Datagridview项都是对象。此时此刻,我所拥有的只是对象的id(一个属性)。我想知道datagridview中保存id对象的行的索引,比如2。

我该如何做到这一点?或者有其他方法可以根据对象的值删除行吗?

如何使用C#根据对象值查找行的索引

可能有一种更干净的方法,但使用LINQ:

private int GetIndexOfRowWithId(DataGridView dataGrid, int id) {
    return dataGrid.Rows.Cast<MyRowObj>().Select((row, index) => new {
        index,
        row
    }).Where(x => x.row.id == id).Select(x => x.index).First();
}

并且不带LINQ:

private int GetIndexOfRowWithId(DataGridView dataGrid, int id) {
    for (int i = 0; i < dataGrid.Rows.Count; i += 1) {
        MyRowObj row = (MyRowObj)dataGrid.Rows[i].Tag; // or.DataBoundItem;
        if (row.id == id) {
            return i;
        }
    }
    throw new ArgumentException("No item with specified id exists in the dataGrid.", "id");
}

如果DataGridView的DataSource是BindingSource,并且底层列表实现FindCore,则可以使用BindingSourceFind()方法,如下所示:

BindingList<YourObject> objectList = new BindingList<YourObject>();
BindingSource source = new BindingSource();
source.DataSource = objectList;
dataGridView1.DataSource = source;
private int GetIndexOfItemById(int id)
{
    return source.Find("Id", id);
}

这可以说是正确的方式,可能会给您带来更好的性能(您可能不需要)。然而,微软并没有让使用它变得容易。框架BindingList对象没有实现FindCore,因此您需要创建自己的IBindingList()(以及实现排序,因为您可能也想要这样做)。

以下是支持Find()的IBindingList实现的代码(取自MSDN)。

protected override bool SupportsSearchingCore
{
    get
    {
        return true;
    }
}
protected override int FindCore(PropertyDescriptor prop, object key)
{
    // Get the property info for the specified property.
    PropertyInfo propInfo = typeof(T).GetProperty(prop.Name);
    T item;
    if (key != null)
    {
        // Loop through the items to see if the key
        // value matches the property value.
        for (int i = 0; i < Count; ++i)
        {
            item = (T)Items[i];
            if (propInfo.GetValue(item, null).Equals(key))
                return i;
        }
    }
    return -1;
}

如果您使用DataTable作为DataSource,那么Find()行为是开箱即用的,但既然您说您有一个自定义对象列表,那么您可能没有。

一种LINQ’ish方法。

var row = dataGrid.Rows.OfType<MyRowObj>().FirstOrDefault(r => r.id == id);
if (row != null) {
   var rowIndex = dataGrid.Rows.IndexOf(row);
   // ... if you need the row index
} else {
   // cry :(
}

在这里,我使用Rows.IndexOf——否则索引可能会被处理到LINQ查询中。SO上有很多这样的例子

快乐的编码。

var query = from DataGridViewRow row in _dataGrid.Rows 
            where  ((DataRowView)row.DataBoundItem).Row == boundedRow
            select row;
if (query.Count() > 0)
{
    // actions
}