问题
I'd like to get the index of a DataGridViewRow, where the value of its first column matches.
My code so far:
string SearchForThis = "test";
int index = from r in dgv.Rows
where r.Cells[0].Value == SearchForThis
select r.Index;
The compiler error:
Could not find an implementation of the query pattern for source type 'System.Windows.Forms.DataGridViewRowCollection'. 'Where' not found. Consider explicitly specifying the type of the range variable 'r'.
回答1:
DataGridViewRowCollection
doesn't implement IEnumerable<T>
, that is why you can't use LINQ, use Enumerable.Cast method.
int index = (dgv.Rows.Cast<DataGridViewRow>()
.Where(r => r.Cells[0].Value == SearchForThis)
.Select(r => r.Index)).First();
Or with Query Syntax:
int index = (from r in dgv.Rows.Cast<DataGridViewRow>()
where r.Cells[0].Value == SearchForThis
select r.Index).First();
You will need to get a single result back from the collection, that is why I have used First
, but remember if there are no items matching the criteria, it will throw an exception. To overcome that see the solution at the end of answer.
See: Enumerable.Cast<TResult> Method
The
Cast<TResult>(IEnumerable)
method enables the standard query operators to be invoked on non-generic collections by supplying the necessary type information. For example,ArrayList
does not implementIEnumerable<T>
, but by callingCast<TResult>(IEnumerable)
on theArrayList
object, the standard query operators can then be used to query the sequence.
(You can also use Enumerable.OfType
method, that will ignore all those which are not DataGridViewRow
, but with DataGridView
, Cast is fine as well)
You can also use FirstOrDefault
to get the row first and then get the index like:
int index = 0;
var item = dgv.Rows.Cast<DataGridViewRow>()
.FirstOrDefault(r => r.Cells[0].Value == (object)1);
if (item != null)
index = item.Index;
回答2:
I generally like these forms, (although the fact that the Rows are not a proper collection is syntactically annoying):
var hit = dgv.Rows.Cast<DataGridViewRow>().First(row => row.Cells["MyColumnName"].Value.Equals(MyIndexValue));
var hit = dgv.Rows.Cast<DataGridViewRow>().FirstOrDefault(row => row.Cells["MyColumnName"].Value.Equals(MyIndexValue));
If you only want the first one, it gets simpler:
var hit = dgv.Rows.Cast<DataGridViewRow>().First(row => row.Cells[0].Value.Equals(MyIndexValue));
来源:https://stackoverflow.com/questions/24083959/using-linq-to-get-datagridview-row-index-where-first-column-has-specific-value