обновление сетки данных при наборе текста

#c# #vb.net #events #datagridview #cell

#c# #vb.net #Мероприятия #datagridview #ячейка

Вопрос:

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

Итак, у меня есть это, и мой вопрос в том, какое событие я должен использовать для проверки ячейки dgw при вводе в нее? Или есть другой способ сделать это?

 Private Sub NRCD_produseDataGridView_CellValueChanged(ByVal sender As Object, ByVal e 
   As System.Windows.Forms.Da-taGridViewCellEventArgs) 
   Handles NRCD_produseDataGridView.???????

   // doesn't matter what is here 

End Sub
  

Спасибо

Ответ №1:

Как вы заметили, событие CellValueChanged не подходит для этой ситуации. Почему? Поскольку значение элемента управления edit еще не перенесено обратно в DataGridView. Событие, которое вы ищете, — это EditingControlShowing. Это даст вам возможность добавлять дескрипторы к фактическому элементу управления редактированием (текстовому полю, выпадающему списку и т.д.), отображаемому в ячейке DataGridViewCell при редактировании. Обратите внимание, что когда ячейка не находится в режиме редактирования, ячейка является просто «изображением» элемента управления редактированием, нарисованного сеткой, это не фактический элемент управления.

Задавая вопрос, связанный с DataGridView, важно поделиться следующим:

  • Привязана ли сетка к источнику данных?
  • Если да, то каков тип базового источника данных?
  • Вы запускаете сетку в виртуальном режиме?

Теперь, поскольку вы не предоставили общий доступ ни к чему из этого, в следующем примере формы предполагается, что сетка:

  • Привязан к DataTable.
  • Запуск в обычном режиме.

введите описание изображения здесь

 Public Class Form1

    Public Sub New()
        Me.InitializeComponent()
        Me.ClientSize = New Size(500, 300)
        Me.table = New DataTable()
        Me.table.Columns.Add("Text", GetType(String))
        Me.table.Columns.Add("Length", GetType(Integer))
        Me.table.Rows.Add("apple", 5)
        Me.table.Rows.Add("banana", 6)
        Me.table.Rows.Add("orange", 6)
        Me.textColumn = New DataGridViewTextBoxColumn() With {.DataPropertyName = "Text", .HeaderText = "Text", .AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill}
        Me.lengthColumn = New DataGridViewTextBoxColumn() With {.DataPropertyName = "Length", .ReadOnly = True, .HeaderText = "Length (Computed)", .Width = 200, .MinimumWidth = 200}
        Me.grid = New DataGridView() With {.Dock = DockStyle.Fill, .AutoGenerateColumns = False, .DataSource = Me.table}
        Me.grid.Columns.AddRange({Me.textColumn, Me.lengthColumn})
        Me.Controls.Add(Me.grid)
    End Sub

    Private Sub HandleEcShowing(sender As Object, e As DataGridViewEditingControlShowingEventArgs) Handles grid.EditingControlShowing
        If (Me.grid.CurrentCell.ColumnIndex = Me.textColumn.Index) Then
            Dim ec As DataGridViewTextBoxEditingControl = DirectCast(e.Control, DataGridViewTextBoxEditingControl)
            Me.UnhookEc(ec) 'Important: Remove handles to avoid recursion.
            Me.HookEc(ec)
        End If
    End Sub

    Private Sub HandleEcTextChanged(sender As Object, e As EventArgs)
        Dim ec As DataGridViewTextBoxEditingControl = DirectCast(sender, DataGridViewTextBoxEditingControl)
        Dim cell As DataGridViewTextBoxCell = DirectCast(Me.grid.CurrentCell, DataGridViewTextBoxCell)
        Me.grid.Rows(cell.RowIndex).Cells(Me.lengthColumn.Index).Value = ec.Text.Length
    End Sub

    Private Sub HandleEcDisposed(sender As Object, e As EventArgs)
        Me.UnhookEc(TryCast(sender, DataGridViewTextBoxEditingControl)) 'Important: This will ensure removal of the hooked handles.
    End Sub

    Private Sub HookEc(ec As DataGridViewTextBoxEditingControl)
        If (Not ec Is Nothing) Then
            AddHandler ec.TextChanged, AddressOf Me.HandleEcTextChanged
            AddHandler ec.Disposed, AddressOf Me.HandleEcDisposed
        End If
    End Sub

    Private Sub UnhookEc(ec As DataGridViewTextBoxEditingControl)
        If (Not ec Is Nothing) Then
            RemoveHandler ec.TextChanged, AddressOf Me.HandleEcTextChanged
            RemoveHandler ec.Disposed, AddressOf Me.HandleEcDisposed
        End If
    End Sub

    Private WithEvents table As DataTable
    Private WithEvents grid As DataGridView
    Private WithEvents textColumn As DataGridViewTextBoxColumn
    Private WithEvents lengthColumn As DataGridViewTextBoxColumn

End Class
  

Комментарии:

1. Привет! Извините за задержку. Я пробовал редактировать Controlshowing, но это мне не помогло. Это действовало как событие нажатия клавиши, вот почему я спросил. Данные привязаны к базе данных access, но я использовал ее только для хранения своих значений (потому что мне не удалось установить связи между таблицами и хорошо работать). В любом случае, я не очень разбираюсь в программировании, и вы сказали что-то о виртуальном / обычном режиме. Можете ли вы сказать мне, в чем разница? Это когда я нажимаю кнопку отладки, а не при использовании приложения на другом компьютере?? Спасибо

Ответ №2:

Я изменил код и добавил текстовое поле.

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

Я заинтересован в том, чтобы код работал таким образом, но это не создает такого странного эффекта.

Если я удалю следующую строку кода в событии HandleEcTextChanged (…)

Я.сетка.Строки (ячейка.RowIndex) .Cells (Me.lengthColumn.Индекс) .Значение = ec.Text.Length

проблема не возникает, но мне нужно программно обновить столбец длины.

Кроме того, если datagridview подключен к базе данных, вы получаете сообщение об ошибке «Поврежден индекс объекта datatable».

Шаги по воспроизведению проблемы:

  1. Измените первую ячейку datagridview «apple».
  2. Нажмите текстовое поле «0000000».
  3. Щелкните на ячейке, измененной выше.
  4. Введите любое значение в текущую ячейку.
  5. В предыдущем пункте возникает проблема. Неправильно записывается в ячейку.

Пожалуйста, помогите.

Спасибо.

 Public Class TextBoxDirectCast

    Private WithEvents table As DataTable
    Private WithEvents grid As DataGridView
    Private WithEvents textColumn As DataGridViewTextBoxColumn
    Private WithEvents lengthColumn As DataGridViewTextBoxColumn
    Private WithEvents texboxtext As TextBox

    Public Sub New()
        Me.InitializeComponent()
        Me.ClientSize = New Size(400, 300)
        Me.table = New DataTable()
        Me.table.Columns.Add("Text", GetType(String))
        Me.table.Columns.Add("Length", GetType(Integer))
        Me.table.Rows.Add("apple", 5)
        Me.table.Rows.Add("banana", 6)
        Me.table.Rows.Add("orange", 6)
        Me.textColumn = New DataGridViewTextBoxColumn() With {.DataPropertyName = "Text", .HeaderText = "Text", .AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill}
        Me.lengthColumn = New DataGridViewTextBoxColumn() With {.DataPropertyName = "Length", .ReadOnly = True, .HeaderText = "Length (Computed)", .Width = 200, .MinimumWidth = 200}
        Me.grid = New DataGridView() With {.Dock = DockStyle.Top, .AutoGenerateColumns = False, .DataSource = Me.table, .TabIndex = 0}
        Me.grid.Columns.AddRange({Me.textColumn, Me.lengthColumn})
        Me.Controls.Add(Me.grid)
        Me.texboxtext = New TextBox With {.Anchor = AnchorStyles.Bottom Or AnchorStyles.Left, .Text = "0000000", .Location = New Point(10, Me.ClientSize.Height - 30), .TabIndex = 1}
        Me.Controls.Add(Me.texboxtext)
        Me.texboxtext.BringToFront()
    End Sub

    Private Sub HandleEcShowing(sender As Object, e As DataGridViewEditingControlShowingEventArgs) Handles grid.EditingControlShowing
        If (Me.grid.CurrentCell.ColumnIndex = Me.textColumn.Index) Then
            Dim ec As DataGridViewTextBoxEditingControl = DirectCast(e.Control, DataGridViewTextBoxEditingControl)
            Me.UnhookEc(ec) 'Important: Remove handles to avoid recursion.
            Me.HookEc(ec)
        End If
    End Sub

    Private Sub HandleEcTextChanged(sender As Object, e As EventArgs)
        Dim ec As DataGridViewTextBoxEditingControl = DirectCast(sender, DataGridViewTextBoxEditingControl)
        Dim cell As DataGridViewTextBoxCell = DirectCast(Me.grid.CurrentCell, DataGridViewTextBoxCell)
        Me.grid.Rows(cell.RowIndex).Cells(Me.lengthColumn.Index).Value = ec.Text.Length
    End Sub

    Private Sub HandleEcDisposed(sender As Object, e As EventArgs)
        Me.UnhookEc(TryCast(sender, DataGridViewTextBoxEditingControl)) 'Important: This will ensure removal of the hooked handles.
    End Sub

    Private Sub HookEc(ec As DataGridViewTextBoxEditingControl)
        If (Not ec Is Nothing) Then
            AddHandler ec.TextChanged, AddressOf Me.HandleEcTextChanged
            AddHandler ec.Disposed, AddressOf Me.HandleEcDisposed
        End If
    End Sub

    Private Sub UnhookEc(ec As DataGridViewTextBoxEditingControl)
        If (Not ec Is Nothing) Then
            RemoveHandler ec.TextChanged, AddressOf Me.HandleEcTextChanged
            RemoveHandler ec.Disposed, AddressOf Me.HandleEcDisposed
        End If
    End Sub

End Class
  

Комментарии:

1. Помогите с этим, пожалуйста, танки