none
DataGridView 单元格的 AutoComplete RRS feed

  • 问题

  • 1.能够实现AutoComplete功能的控件一般有textbox、combobox.
    2.在Datagridview中也可以将列设定为 DataGridViewTextBoxColumn 和 DataGridViewComboBoxColumn 来实现 AutoComplete 功能。

    问题:由于 DataGridViewTextBoxColumn 和 DataGridViewComboBoxColumn 的 autocomplete 功能和外观太简单,我想实现复杂一点的,
            比如:我想将 autocoplete 功能改为一个由 DataGridView 来实现的界面,以实现更加全面的检索(包括:检索多列关键字,自定义背景、排序,图标等),
            单元格的类型还是上面说的两种类型之一,请问该如何实现呢?
    2009年6月18日 6:18

答案

  • 1. 关闭之前结束编辑状态试试
    2. 通过 DataGridView.GetCellDisplayRectangle 方法获取坐标

    知识改变命运,奋斗成就人生!
    • 已标记为答案 Chengli 2009年7月14日 2:24
    2009年7月2日 3:49
    版主

全部回复

  • 你可以自己做个控件完成你的逻辑, 在 DataGridView 的单元格获得焦点时,把你做的这个控件显示在当前单元格的下方,在 DataGridView 单元格的键盘事件中根据输入内容刷新你做的控件的内容显示

    知识改变命运,奋斗成就人生!
    2009年6月19日 6:20
    版主
  • 这个我明白,但问题是:

    当弹出这么个控件时,我若用鼠标点击它,那么datagridview的单元格会失去焦点而结束编辑模式。

    我想在单击这个控件时,Datagridview控件的单元格不失去焦点,因为这时我还处于编辑中,只不过我正在弹出的这个控件中选择或浏览数据。

    有没有一个折中的方法,让我既能单击该控件,又不让Datagridview单元格失去焦点? 多谢!
    2009年6月20日 2:36
  • 为何不在选中数据后重新字焦点赋给单元格呢?
    知识改变命运,奋斗成就人生!
    2009年6月20日 2:42
    版主
  • 因为在这一操作之前,单元格会结束编辑。而单元格结束编辑时,会存在验证逻辑,会报错。我想,很少人希望看到这一点吧?
    因此,才考虑不让单元格失去焦点。
    2009年6月20日 2:45
  • 失去焦点是必然的,因为你需要在另外的控件上进行操作,你可以考虑这种折中的办法,在验证时判断 AutoComplate 控件是否显示,如果是显示状态就不验证
    知识改变命运,奋斗成就人生!
    2009年6月20日 2:52
    版主
  • 这也是个折中的方法。不过这样的话,单元格还是会闭合。
    我见过“金蝶KIS”的输入界面就能实现这样的效果,他的提示列表显示了滚动条,但是不能用鼠标滚轮滚动,可能是假的焦点现象,真的焦点应该还在单元格里面。
    不知道他们怎么做的,版主能否帮我分析分析?
    2009年6月20日 3:00
  • 这种可能是用颜色突出显示哦,我们也可以做到, 在单元格中响应键盘的方向键进行 AutoComplate 中进行项的颜色切换
    知识改变命运,奋斗成就人生!
    2009年6月20日 3:07
    版主
  • 对,用键盘的方向键可以实现,我也试过,但是一用鼠标就不行。他们的就可以用鼠标点击,而且焦点还在单元格里面。
    我在考虑他们是不是根本就没有给这个控件焦点,当鼠标点击时,根据坐标来判断是否取消鼠标的点击命令,然后再结合键盘来模拟。
    2009年6月20日 3:11
  • 如果是这样的话,我却不知道如何取消鼠标的点击命令。
    如果不是,还请版主费心~
    2009年6月20日 3:13
  • 你好,

    你是怎么显示自定义的控件的,是在使用BeginEdit吗?看下下面这个例子如何在datagridview中显示TextBox控件的:

    Public Class Form2
        Dim ds As New DataSet
        Private dt As New DataTable()
        Dim textbox1 As New TextBox
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            dt.Columns.Add("aa")
            dt.Columns.Add("bb")
            dt.Columns.Add("time", GetType(Double))
            Dim dt1 As DataTable = New DataTable
            dt1.Columns.Add("cc")
            dt1.Columns.Add("dd", GetType(Integer))
            Dim str() As String = New String(4) {"Billy", "Diego", "Ray", "Anelca", "Jay"}
            For i As Integer = 0 To 40
                dt.Rows.Add(i, "bb" & i, i * 100.12)
                'dt1.Rows.Add(str(i), i)
            Next
            dt.AcceptChanges()
            ds.Tables.Add(dt)
            Me.DataGridView1.DataSource = ds
            Me.DataGridView1.DataMember = ds.Tables(0).TableName
            Dim combo As DataGridViewComboBoxColumn = New DataGridViewComboBoxColumn()
            combo.HeaderText = "test"
            combo.DataSource = dt1
            combo.DisplayMember = "cc"
            combo.ValueMember = "dd"
            Me.DataGridView1.Columns.Add(combo)
            Me.textbox1.Visible = False
            Me.Controls.Remove(textbox1)
            textbox1.Multiline = True
            Me.DataGridView1.Controls.Add(textbox1)
        End Sub
        Private Sub DataGridView1_CellBeginEdit(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellCancelEventArgs) Handles DataGridView1.CellBeginEdit
            If (e.ColumnIndex = 1) Then
                Dim rect As Rectangle = Me.DataGridView1.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, True)
                textbox1.Location = rect.Location
                textbox1.Width = rect.Width
                textbox1.Height = Me.DataGridView1.Height / 4
                textbox1.Text = Me.DataGridView1.CurrentCell.Value.ToString()
                textbox1.Visible = True
            End If
        End Sub
        Private Sub DataGridView1_CellEndEdit(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellEndEdit
            If (e.ColumnIndex = 1) Then
                Me.DataGridView1.CurrentCell.Value = textbox1.Text
                Me.textbox1.Visible = False
            End If
        End Sub
        Private Sub DataGridView1_Scroll(ByVal sender As System.Object, ByVal e As System.Windows.Forms.ScrollEventArgs) Handles DataGridView1.Scroll
            If (DataGridView1.CurrentCell.ColumnIndex = 1) Then
                If textbox1.Visible = True Then
                    Dim r As Rectangle = Me.DataGridView1.GetCellDisplayRectangle(Me.DataGridView1.CurrentCell.ColumnIndex, Me.DataGridView1.CurrentCell.RowIndex, True)
                    textbox1.Location = r.Location
                    textbox1.Width = r.Width
                    textbox1.Height = DataGridView1.Height / 4
                End If
            End If
        End Sub
    End Class
    






    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    2009年6月22日 2:46
    版主
  • 失去焦点是必然的,因为你需要在另外的控件上进行操作,你可以考虑这种折中的办法,在验证时判断 AutoComplate 控件是否显示,如果是显示状态就不验证
    知识改变命运,奋斗成就人生!

    我再次用你这个方法尝试了几次,然后结合鼠标的单击,可以成功(如果Autocomplete控件显示,就e.cancel=true。如果鼠标点击这个控件之外,就使Autoplete控件隐藏,同时datagridview就EndEdit)。但是存在一些问题:
    1.单元格处于编辑模式是,单击窗体的关闭按钮会没反应。
    2.如何定位这个Autocomplete控件的位置?我想让他紧接着显示在单元格的下面。如果Datagridview没有滚动条的话,Autocomplete控件的位置就可以根据列和行计算出来,但是如果有滚动条,就不能根据当前单元格的所在的行计算,怎么办呢?
    2009年7月2日 3:34
  • 1. 关闭之前结束编辑状态试试
    2. 通过 DataGridView.GetCellDisplayRectangle 方法获取坐标

    知识改变命运,奋斗成就人生!
    • 已标记为答案 Chengli 2009年7月14日 2:24
    2009年7月2日 3:49
    版主
  • private void Form1_FormClosing(object sender, FormClosingEventArgs e)
            {
                dgv1.EndEdit();
            }
    试了一下,这样也不行。只是将编辑模式关闭,不能关闭窗体。
    2009年7月2日 3:54
  • 如果使用了 BindingSource 需要调用 BindingSource.EndEdit();
    知识改变命运,奋斗成就人生!
    2009年7月2日 4:03
    版主
  • 由于是试验阶段,没有任何绑定,只是用VS设计器添加了几列。
    private void Form1_FormClosing(object sender, FormClosingEventArgs e)
            {
                dgv1.EndEdit();
            }
    这段代码仅仅起到了EndEdit作用,之后关闭窗体的消息好像被阻断了,不见了。
    2009年7月2日 4:21
  • 哥们,我也遇到同样的问题了;

    你是怎么解决的啊?分享下不


    大其心,可容天下之物; 虚其心,可受天下之善;

    2012年5月3日 10:41