I\'m trying to select the first row where the cell value starts with the same keychar the user pressed. That\'s the part that is giving me trouble.
Here\'s how I\'m hand
Might be a case issue, is the Value in Cells["Name"] start with a capital letter? Try using ToUpper or ToLower on both; or you could try StartsWith(e.KeyChar, true) to ignoreCase. If you are trying to select the row, you'll want to do dataGridView1.Rows[i].Selected = true
I use this in VB.NET. You can use http://www.developerfusion.com/tools/ to convert to C Sharp.
I wrote a method that will select row letter typed. The function is called in the KeysPress event handler of the DataGridView.
Method:
'user types letter in dgv, method will select the column starting with that letter if it exists or else next letter existing in dgv
Public Shared Sub GoToLetterTypedInDataGridView(ByVal dgv As DataGridView, ByVal columnName As String, ByVal columnPosition As Integer, ByVal letterTyped As Char)
Try
Dim dt As DataTable = dgv.DataSource
Dim letter As Char = letterTyped
Dim dv As DataView = New DataView(dt)
Dim hasCount As Boolean = False
While (Not hasCount)
dv.Sort = columnName
dv.RowFilter = columnName & " like '" & letter & "%'"
If dv.Count > 0 Then
hasCount = True
Dim x As String = dv(0)(columnPosition).ToString()
Dim bs As New BindingSource
bs.DataSource = dt
dgv.BindingContext(bs).Position = bs.Find(columnName, x)
dgv.CurrentCell = dgv(0, bs.Position)
Else
If letter = "z" Then
letter = "a"
ElseIf letter = "Z" Then
letter = "A"
Else : letter = Chr(Asc(letter) + 1)
End If
End If
End While
Catch ex As Exception
Dim stackframe As New Diagnostics.StackFrame(1)
Throw New Exception("An error occurred in routine, '" & stackframe.GetMethod.ReflectedType.Name & "." & System.Reflection.MethodInfo.GetCurrentMethod.Name & "'." & Environment.NewLine & " Message was: '" & ex.Message & "'")
End Try
End Sub
Then to call:
Private Sub dgvNew_KeyPress(sender As Object, e As System.Windows.Forms.KeyPressEventArgs) Handles dgvNew.KeyPress
Try
If dgvNew.RowCount > 0 Then
GoToLetterTypedInDataGridView(dgvNew, "columnName", 0, e.KeyChar)
End If
Catch ex As Exception
Dim stackframe As New Diagnostics.StackFrame(1)
Throw New Exception("An error occurred in routine, '" & stackframe.GetMethod.ReflectedType.Name & "." & System.Reflection.MethodInfo.GetCurrentMethod.Name & "'." & Environment.NewLine & " Message was: '" & ex.Message & "'")
End Try
End Sub
Hope this helps! Amber
The edited answer in the original question doesn't support jumping to the next letter if there are multiple instances of names starting with the same letter. Here is an edited answer which support this feature:
private void dataGridView1_KeyPress(object sender, KeyPressEventArgs e)
{
if (Char.IsLetter(e.KeyChar))
{
int index = 0;
// This works only if dataGridView1's SelectionMode property is set to FullRowSelect
if (dataGridView1.SelectedRows.Count > 0 )
{
index = dataGridView1.SelectedRows[0].Index + 1
}
for (int i = index; i < (dataGridView1.Rows.Count + index); i++)
{
if (dataGridView1.Rows[i % dataGridView1.Rows.Count].Cells["Name"].Value.ToString().StartsWith(e.KeyChar.ToString(), true, CultureInfo.InvariantCulture))
{
foreach (var row in dataGridView1.Rows.Cast<DataGridViewRow>().Where(t => t.Selected))
{
row.Selected = false;
}
dataGridView1.Rows[i % dataGridView1.Rows.Count].Cells[0].Selected = true;
return; // stop looping
}
}
}
}
This is a VS2008 VB.NET DataGridView extension meant to do kind of what you are doing but using a TextBox for searching information (not designed with case in mind but could easily be added). This extension works so perhaps there is something that might be helpful. I did notice that your code selects a row using select where mine uses CurrentCell.
<Runtime.CompilerServices.Extension()> _
Public Function PartSeek(ByVal GridView As DataGridView, ByVal ColumnName As String, ByVal Value As String, ByVal Part As Boolean) As Boolean
Dim Located As Boolean = False
If GridView.Columns.Contains(ColumnName) Then
Dim SingleRow As DataGridViewRow
If Part Then
SingleRow = (From Rows In GridView.Rows.Cast(Of DataGridViewRow)() _
Where Rows.Cells(ColumnName).Value.ToString().Contains(Value)).FirstOrDefault
Else
SingleRow = (From Rows In GridView.Rows.Cast(Of DataGridViewRow)() _
Where Rows.Cells(ColumnName).Value.ToString() = Value).FirstOrDefault
End If
If Not IsNothing(SingleRow) Then
If GridView.CurrentCell.RowIndex <> SingleRow.Index Then
GridView.CurrentCell = GridView(0, SingleRow.Index)
End If
DirectCast(GridView.Parent, Form).ActiveControl = GridView
Located = True
End If
Return Located
Else
Throw New Exception("Column '" & ColumnName & "' not contained in this DataGridView")
End If
End Function
if (Char.IsLetterOrDigit(e.KeyChar))
{
foreach (DataGridViewRow dgvRow in myDgv.Rows)
{
if (dgvRow.Cells["ColumnName"].FormattedValue
.ToString().StartsWith(e.KeyChar.ToString(), true, CultureInfo.InvariantCulture))
{
dgvRow.Selected = true;
break;
}
}
}
If the DGV is set up to allow Multi-Select then you'd obviously want to deselect any existing selection.