Cerca datagridview premendo un tasto dall'utente
-
18-09-2019 - |
Domanda
Sto provando a selezionare la prima riga in cui il valore della cella inizia con lo stesso carattere chiave premuto dall'utente.Questa è la parte che mi dà problemi.
Ecco come sto gestendo l'evento (aggiornato con soluzione funzionante):
private void dataGridView1_KeyPress(object sender, KeyPressEventArgs e)
{
if (Char.IsLetter(e.KeyChar))
{
for (int i = 0; i < (dataGridView1.Rows.Count); i++)
{
if (dataGridView1.Rows[i].Cells["Name"].Value.ToString().StartsWith(e.KeyChar.ToString(), true, CultureInfo.InvariantCulture))
{
dataGridView1.Rows[i].Cells[0].Selected = true;
return; // stop looping
}
}
}
}
Sono sicuro che sia qualcosa di semplice che sto trascurando, ma per quanto mi riguarda non riesco a capire di cosa si tratta.
MODIFICARE
Aggiornato il codice con la soluzione applicata
Soluzione
Potrebbe trattarsi di un problema, il valore nelle celle ["Nome"] inizia con una lettera maiuscola?Prova a utilizzare ToUpper o ToLower su entrambi;oppure potresti provare StartsWith(e.KeyChar, true) per ignorareCase.Se stai provando a selezionare la riga, ti consigliamo di eseguire dataGridView1.Rows[i].Selected = true
Altri suggerimenti
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;
}
}
}
Se il DGV è impostato per consentire la selezione multipla, ovviamente vorrai deselezionare qualsiasi selezione esistente.
La risposta modificata nella domanda originale non supporta il passaggio alla lettera successiva se sono presenti più istanze di nomi che iniziano con la stessa lettera.Ecco una risposta modificata che supporta questa funzione:
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
}
}
}
}
Questa è un'estensione VS2008 VB.NET DataGridView pensata per fare quello che stai facendo ma utilizzando un TextBox per la ricerca di informazioni (non progettato pensando al caso ma potrebbe essere facilmente aggiunto).Questa estensione funziona, quindi forse c'è qualcosa che potrebbe essere utile.Ho notato che il tuo codice seleziona una riga utilizzando select dove il mio utilizza 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
Lo uso in VB.NET.Puoi usare http://www.developerfusion.com/tools/ per convertire in Do diesis.
Ho scritto un metodo che selezionerà la lettera della riga digitata.La funzione viene chiamata nel gestore eventi KeysPress di DataGridView.
Metodo:
'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
Quindi chiamare:
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
Fine sott
Spero che questo ti aiuti!Ambra