Поиск данных по просмотру клавиш пользователя - PullRequest
7 голосов
/ 28 апреля 2009

Я пытаюсь выбрать первую строку, где значение ячейки начинается с той же клавиши, которую нажал пользователь. Это та часть, которая доставляет мне неприятности.

Вот как я обрабатываю событие ( дополнено рабочим решением ):

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

Я уверен, что это что-то простое, что я пропускаю, но по жизни я не могу понять, что это такое.

EDIT

Обновлен код с примененным решением

Ответы [ 5 ]

4 голосов
/ 28 апреля 2009

Может быть проблема в кейсе, значение в ячейках ["Name"] начинается с заглавной буквы? Попробуйте использовать ToUpper или ToLower на обоих; или вы можете попробовать StartsWith (e.KeyChar, true) игнорироватьCase. Если вы пытаетесь выбрать строку, вам нужно сделать dataGridView1.Rows [i] .Selected = true

2 голосов
/ 23 октября 2014

Отредактированный ответ в исходном вопросе не поддерживает переход к следующей букве, если несколько имен начинаются с одной и той же буквы. Вот отредактированный ответ, который поддерживает эту функцию:

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
            }
        }
    }
}
2 голосов
/ 28 апреля 2009
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;
        }
    }
}

Если DGV настроен для разрешения множественного выбора, то, очевидно, вы захотите отменить выбор любого существующего выбора.

1 голос
/ 10 ноября 2012

Я использую это в VB.NET. Вы можете использовать http://www.developerfusion.com/tools/ для преобразования в C Sharp.

Я написал метод, который будет выбирать набранную букву строки. Функция вызывается в обработчике событий KeysPress DataGridView.

Метод:

'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

Тогда позвонить:

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

Надеюсь, это поможет! Amber

1 голос
/ 30 апреля 2009

Это расширение VS2008 VB.NET DataGridView, предназначенное для того, чтобы делать то, что вы делаете, но с использованием TextBox для поиска информации (не разработано с учетом обстоятельств, но может быть легко добавлено). Это расширение работает, так что, возможно, есть что-то, что может быть полезным. Я заметил, что ваш код выбирает строку, используя select, где мой использует 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
...