Как найти индекс строки на основе значения объекта с помощью C #? - PullRequest
3 голосов
/ 15 июня 2011

У меня есть сетка данных, и я хочу удалить из нее определенную строку (сетка данных не привязана к данным). Для удаления мне нужен индекс строки. Элементы Datagridview - это все объекты. На данный момент все, что у меня есть, это идентификатор (свойство) объекта. Я хочу знать индекс строки в datagridview, которая содержит объект id, скажем, 2.

Как мне это сделать? Или есть другой способ удаления строки на основе значения объекта?

Ответы [ 4 ]

3 голосов
/ 15 июня 2011

Возможно, есть более чистый способ, но с 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");
}
2 голосов
/ 15 июня 2011

Если DataSrid вашего DataGridView является BindingSource и базовый список реализует FindCore, то вы можете использовать метод BindingSource Find () следующим образом:

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

Возможно, это правильный способ сделать это и может дать вам лучшую производительность (которая вам, вероятно, не понадобится). Тем не менее, Microsoft не сделала это простым. Каркасный объект BindingList не реализует FindCore, поэтому вам нужно будет создать собственный IBindingList () (а также реализовать сортировку, поскольку вы, вероятно, тоже этого хотите).

Вот код для реализации IBindingList, которая поддерживает Find () (взято из 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 в качестве источника данных, то вы получаете поведение Find () из коробки, но, поскольку вы говорите, что у вас есть список пользовательских объектов, вы, вероятно, нет.

1 голос
/ 15 июня 2011

Подход 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.(Как тот, который ICR добавил к своему ответу:)

Удачное кодирование.

0 голосов
/ 27 января 2014
var query = from DataGridViewRow row in _dataGrid.Rows 
            where  ((DataRowView)row.DataBoundItem).Row == boundedRow
            select row;

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