C# 在用户按键上搜索 datagridview

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/797946/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 01:35:05  来源:igfitidea点击:

Search datagridview on user keypress

c#.netwinformsdatagridviewkeypress

提问by Johann J.

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.

我正在尝试选择单元格值以用户按下的相同 keychar 开头的第一行。这就是给我带来麻烦的部分。

Here's how I'm handling the event (updated with working solution):

这是我处理事件的方式(使用工作解决方案更新):

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

I'm sure it's something simple that I'm overlooking, but for the life of me can't figure out what it is.

我敢肯定这是我忽略的一些简单的事情,但对于我的生活,我无法弄清楚它是什么。

EDIT

编辑

Updated the code with solution applied

使用解决方案更新了代码

采纳答案by SwDevMan81

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

可能是大小写问题,Cells["Name"] 中的值是否以大写字母开头?尝试在两者上使用 ToUpper 或 ToLower;或者你可以尝试 StartsWith(e.KeyChar, true) 来忽略大小写。如果您尝试选择行,则需要执行 dataGridView1.Rows[i].Selected = true

回答by xyz

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.

如果 DGV 设置为允许多选,那么您显然希望取消选择任何现有选择。

回答by user39074

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.

这是一个 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

回答by Amberlea Moore

I use this in VB.NET. You can use http://www.developerfusion.com/tools/to convert to C Sharp.

我在 VB.NET 中使用它。您可以使用http://www.developerfusion.com/tools/转换为 C Sharp。

I wrote a method that will select row letter typed. The function is called in the KeysPress event handler of the DataGridView.

我写了一个方法来选择输入的行字母。该函数在 DataGridView 的 KeysPress 事件处理程序中调用。

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

希望这可以帮助!琥珀色

回答by TBD

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