nawfal
nawfal

Reputation: 73183

How to find index of a row based on the object value using C#?

I have a datagridview, and I want to remove a particular row from it (datagridview is not data bound). To remove, I need the index of the row. Datagridview items are all objects. At this moment, all I have is the id (a property) of the object. I want to know the index of the row in datagridview which holds the object of id, say 2.

How do I accomplish this? Or is there another way of deleting a row based on an object's value?

Upvotes: 3

Views: 15091

Answers (4)

Doctor Marvin
Doctor Marvin

Reputation: 21

var query = from DataGridViewRow row in _dataGrid.Rows 
            where  ((DataRowView)row.DataBoundItem).Row == boundedRow
            select row;

if (query.Count() > 0)
{
    // actions
}

Upvotes: 0

David Hall
David Hall

Reputation: 33153

If your DataGridView's DataSource is a BindingSource and the underlying list implements FindCore then you can use the BindingSource Find() method like so:

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

This is arguably the right way of doing it, and might give you better performance (which you probably won't need). However, Microsoft haven't made using this easy. The framework BindingList object does not implement FindCore so you will need to create your own IBindingList() (as well as implementing sorting, since you probably want that too).

Here is the code for an IBindingList implementation that supports Find() (taken from 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;
}

If you are using a DataTable as your DataSource then you get the Find() behaviour out of the box, but since you say you have a list of custom objects, you probably aren't.

Upvotes: 2

ICR
ICR

Reputation: 14162

There's probably a cleaner way, but with 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();
}

and without 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");
}

Upvotes: 3

user166390
user166390

Reputation:

A LINQ'ish approach.

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 :(
}

Here I use Rows.IndexOf -- otherwise the index could be worked into the LINQ query. There are a number of such examples on SO. (Like the one ICR added to his answer :)

Happy coding.

Upvotes: 1

Related Questions