Флажки не позволяют myCurrencyManager.AddNew () работать должным образом - PullRequest
0 голосов
/ 18 апреля 2020

У меня полнофункциональное приложение Windows для форм, разработанное с сеткой данных только для чтения, привязанной к базе данных Access.
Текстовые поля с привязкой к данным используются для редактирования полей. Затем я добавил 3 поля-флажка в БД, в datagridview и в форму. Затем добавили chkName.DataBindings.Add("Checked", DBTable,"Field"), как текстовые поля. Флажки работают правильно, отображая правильные данные.

Только теперь, когда я пытаюсь добавить строку с помощью myCurrencyManager.AddNew(), она не работает. Он ничего не делает, кроме добавления недоступной строки в конец таблицы данных. Когда я закомментирую строки Checkbox DataBindings, все работает правильно (без функциональных флажков).

Есть идеи, что не так?

Вот код:

Public Class frmRoutes
    Dim RoutesConnection As OleDbConnection
    Dim JS1Adapter As New OleDbDataAdapter
    Dim JS1Table As New DataTable("JOBSITES")
    Dim JSBS As BindingSource
    Dim JS1State As String = "Edit"

    Private Sub frmRoutes_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        RoutesConnection = New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0; Data Source = C:\Microsoft\JS1TestDB.mdb")
        RoutesConnection.Open()
        Dim JobSitesCommand = New OleDbCommand _
        ("SELECT REF, STREET, CITY, SPEC, HELPER " +
        "FROM Jobsites ORDER BY REF", RoutesConnection)

        JS1Adapter.SelectCommand = JobSitesCommand
        JS1Adapter.Fill(JS1Table)

        JSBS = New BindingSource()
        JSBS.DataSource = JS1Table
        grdJobSites.DataSource = JSBS

        txtRef.DataBindings.Add("Text", JSBS, "REF")
        txtStreet.DataBindings.Add("Text", JSBS, "STREET")
        txtCity.DataBindings.Add("Text", JSBS, "CITY")
        'chkSpecial.DataBindings.Add("Checked", JSBS, "SPEC")  'THESE 2 CHECKBOX DATABINDINGS CAUSE THE 'ADDNEW' METHOD TO FAIL
        'chkHelper.DataBindings.Add("Checked", JSBS, "HELPER")
    End Sub

    Private Sub btnAdd_Click(sender As Object, e As EventArgs) Handles btnAdd.Click
        Try
            JSBS.AddNew()
        Catch ex As Exception
            MessageBox.Show("Error Adding a New row.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
        JS1State = "Add"
    End Sub

    Private Sub btnCancel_Click(sender As Object, e As EventArgs) Handles btnCancel.Click
        JSBS.CancelEdit()
        JS1State = "View"
    End Sub
End Class

1 Ответ

0 голосов
/ 20 апреля 2020

Проблема в точности, как я уже сказал: обнуляемые данные. Я только что проверил этот код (фактический минимальный пример):

Public Class Form1

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim table As New DataTable

        With table.Columns
            .Add("Name", GetType(String))
            .Add("Flag", GetType(Boolean))
        End With

        With table.Rows
            .Add("Peter", True)
            .Add("Paul", False)
            .Add("Mary", True)
        End With

        BindingSource1.DataSource = table
        TextBox1.DataBindings.Add("Text", BindingSource1, "Name")
        CheckBox1.DataBindings.Add("Checked", BindingSource1, "Flag")
    End Sub

End Class

и возникла недопустимая исключительная ситуация при добавлении новой строки (через BindingNavigator), поскольку столбец Flag содержал DBNull.Value от по умолчанию и не может быть приведен к типу Boolean, что требуется для свойства Checked. Есть два возможных решения. Лучший вариант зависит от того, хотите ли вы иметь возможность сохранять нулевые значения или нет.

  1. Если вы не хотите сохранять нулевые значения, укажите значение по умолчанию Boolean для этого столбца. Это, вероятно, будет False, но может быть True, если вы этого хотите. Таким образом, при добавлении новой строки этот столбец уже содержит значение Boolean, которое совместимо со свойством Checked. В моем примере это:
.Add("Flag", GetType(Boolean))

становится следующим:

.Add("Flag", GetType(Boolean)).DefaultValue = False

В вашем случае вам нужно будет получить соответствующий столбец из DataTable после заполнения это и установите это свойство.

Задайте для свойства ThreeState CheckBox значение True, свяжите его со свойством CheckState вместо свойства Checked и выполните собственный перевод данных Nullable Boolean в источнике данных и CheckState значения в контроле. Внесение этого изменения в мой пример может выглядеть следующим образом:
Public Class Form1

    Private WithEvents checkStateBinding As Binding

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim table As New DataTable

        With table.Columns
            .Add("Name", GetType(String))
            .Add("Flag", GetType(Boolean))
        End With

        With table.Rows
            .Add("Peter", True)
            .Add("Paul", False)
            .Add("Mary", True)
        End With

        BindingSource1.DataSource = table
        TextBox1.DataBindings.Add("Text", BindingSource1, "Name")

        checkStateBinding = New Binding("CheckState", BindingSource1, "Flag")

        CheckBox1.DataBindings.Add(checkStateBinding)
    End Sub

    Private Sub CheckStateBinding_Format(sender As Object, e As ConvertEventArgs) Handles checkStateBinding.Format
        'Convert from nullable Boolean to CheckState.
        If TryCast(e.Value, DBNull) Is DBNull.Value Then
            e.Value = CheckState.Indeterminate
        ElseIf CBool(e.Value) Then
            e.Value = CheckState.Checked
        Else
            e.Value = CheckState.Unchecked
        End If
    End Sub

    Private Sub CheckStateBinding_Parse(sender As Object, e As ConvertEventArgs) Handles checkStateBinding.Parse
        'Convert from CheckState to nullable Boolean.
        Select Case DirectCast(e.Value, CheckState)
            Case CheckState.Indeterminate
                e.Value = DBNull.Value
            Case CheckState.Checked
                e.Value = True
            Case CheckState.Unchecked
                e.Value = False
        End Select
    End Sub

End Class

Binding вызывает событие Format, когда ему нужно получить данные из источника данных для элемента управления и его Parse событие, когда необходимо получить данные из элемента управления для источника данных. Если типы и / или значения не совпадают между собой, вы можете сделать свой собственный перевод.

...