Проблема в точности, как я уже сказал: обнуляемые данные. Я только что проверил этот код (фактический минимальный пример):
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
. Есть два возможных решения. Лучший вариант зависит от того, хотите ли вы иметь возможность сохранять нулевые значения или нет.
- Если вы не хотите сохранять нулевые значения, укажите значение по умолчанию
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
событие, когда необходимо получить данные из элемента управления для источника данных. Если типы и / или значения не совпадают между собой, вы можете сделать свой собственный перевод.