Custom Control keeps triggering dataset has changes

taz8020
taz8020 used Ask the Experts™
on
Hi I have a custom control i have created with 6 textboxes, it works great apart from it keeps triggering the dataset has changes even when the data has not changed.

Below is how i set the binding. Please tel me what i am doing wrong.
I have tried removing the  OnValueChanged(ppe) and still get same issue

    <System.ComponentModel.Bindable(True, BindingDirection.TwoWay)>
    Public Property PostCode As String
        Get
            Return Me.PostCodeTextBox1.Postcode
        End Get
        Set(ByVal value As String)
            Me.PostCodeTextBox1.Postcode = value
            Dim ppe As PropertyChangedEventArgs = New PropertyChangedEventArgs("PostCode")
            OnValueChanged(ppe)
        End Set
    End Property

Open in new window

Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®

Commented:
You want to ensure that value and Postcode are not equal before setting the Postcode and also issuing the PropertyChanged event; e.g. -
<System.ComponentModel.Bindable(True, BindingDirection.TwoWay)>
Public Property PostCode As String
    Get
        Return Me.PostCodeTextBox1.Postcode
    End Get
    Set(ByVal value As String)
        If Not Equals(Me.PostCodeTextBox1.Postcode, value) Then
            Me.PostCodeTextBox1.Postcode = value
            Dim ppe As PropertyChangedEventArgs = New PropertyChangedEventArgs("PostCode")
            OnValueChanged(ppe)
        End If
    End Set
End Property

Open in new window

But in case there is something else going on here, could you share the complete code of your custom control?

-saige-

Author

Commented:
Hi it_sagie i just tried that and still does not work.

here is the full control, I have tried what you said and commented out the OnValueChanged but still get same issue.
To make sure it was not something else causing it, I have tried removing the control. Once removed it all works as it should.

Imports System.ComponentModel
Imports System.Drawing
Imports System.Windows.Forms

Public Class AddressGroupBox
    Public Event ValueChanged As PropertyChangedEventHandler

    Public CountryName As String
    Public CountryNameAndCode As String
    Public AreaOfWorld As String

    Private Sub PostCodeTextBox1_SearchBtnClicked(sender As Object, e As EventArgs) Handles PostCodeTextBox1.SearchBtnClicked
        'ResetForm() ' dont use this as clears ref

        Me.BusinessNameTextBox.Text = ""
        Me.AddressLine1TextBox.Text = ""
        Me.AddressLine2TextBox.Text = ""
        Me.AddressLine3TextBox.Text = ""
        Me.PostalTownTextBox.Text = ""
        Me.CountyTextBox.Text = ""
        Me.PostCodeTextBox1.Text = ""

        Me.BusinessNameTextBox.Text = PostCodeTextBox1.myPostcodeForm.OrganisationName

        If PostCodeTextBox1.myPostcodeForm.BuildingNumber.Length > 0 And PostCodeTextBox1.myPostcodeForm.SubBuildingName.Length > 0 Then
            Me.AddressLine1TextBox.Text = PostCodeTextBox1.myPostcodeForm.BuildingNumber & ", " & PostCodeTextBox1.myPostcodeForm.SubBuildingName
        ElseIf PostCodeTextBox1.myPostcodeForm.BuildingNumber.Length > 0 Then
            Me.AddressLine1TextBox.Text = PostCodeTextBox1.myPostcodeForm.BuildingNumber
        ElseIf PostCodeTextBox1.myPostcodeForm.SubBuildingName.Length > 0 Then
            Me.AddressLine1TextBox.Text = PostCodeTextBox1.myPostcodeForm.SubBuildingName
        End If

        Me.AddressLine2TextBox.Text = PostCodeTextBox1.myPostcodeForm.BuildingName

        Me.AddressLine3TextBox.Text = PostCodeTextBox1.myPostcodeForm.Street
        Me.PostalTownTextBox.Text = PostCodeTextBox1.myPostcodeForm.PostTown
        Me.CountyTextBox.Text = PostCodeTextBox1.myPostcodeForm.County
        If Me.CountyTextBox.TextLength = 0 Then
            Me.CountyTextBox.Text = PostCodeTextBox1.County
        End If
        Me.PostCodeTextBox1.Text = PostCodeTextBox1.Postcode

        CountryName = CountryDropDownList1.CountryName
        CountryNameAndCode = CountryDropDownList1.CountryNameAndCode
        AreaOfWorld = CountryDropDownList1.AreaOfWorld
    End Sub

    <System.ComponentModel.Bindable(True, BindingDirection.TwoWay)>
    Public Property BusinessName As String
        Get
            Return Me.BusinessNameTextBox.Text
        End Get
        Set(ByVal value As String)
            If Not Equals(Me.BusinessNameTextBox.Text, value) Then
                Me.BusinessNameTextBox.Text = value
                'Dim ppe As PropertyChangedEventArgs = New PropertyChangedEventArgs("BusinessName")
                'OnValueChanged(ppe)
            End If

        End Set
    End Property

    <System.ComponentModel.Bindable(True, BindingDirection.TwoWay)>
    Public Property AddressLine1 As String
        Get
            Return Me.AddressLine1TextBox.Text
        End Get
        Set(ByVal value As String)
            If Not Equals(Me.AddressLine1TextBox.Text, value) Then
                Me.AddressLine1TextBox.Text = value
                'Dim ppe As PropertyChangedEventArgs = New PropertyChangedEventArgs("AddressLine1")
                'OnValueChanged(ppe)
            End If

        End Set
    End Property
    <System.ComponentModel.Bindable(True, BindingDirection.TwoWay)>
    Public Property AddressLine2 As String
        Get
            Return Me.AddressLine2TextBox.Text
        End Get
        Set(ByVal value As String)
            If Not Equals(Me.AddressLine2TextBox.Text, value) Then
                Me.AddressLine2TextBox.Text = value
                'Dim ppe As PropertyChangedEventArgs = New PropertyChangedEventArgs("AddressLine2")
                'OnValueChanged(ppe)
            End If
        End Set
    End Property
    <System.ComponentModel.Bindable(True, BindingDirection.TwoWay)>
    Public Property AddressLine3 As String
        Get
            Return Me.AddressLine3TextBox.Text
        End Get
        Set(ByVal value As String)
            If Not Equals(Me.AddressLine3TextBox.Text, value) Then
                Me.AddressLine3TextBox.Text = value
                'Dim ppe As PropertyChangedEventArgs = New PropertyChangedEventArgs("AddressLine3")
                'OnValueChanged(ppe)
            End If

        End Set
    End Property
    <System.ComponentModel.Bindable(True, BindingDirection.TwoWay)>
    Public Property PostalTown As String
        Get
            Return Me.PostalTownTextBox.Text
        End Get
        Set(ByVal value As String)
            If Not Equals(Me.PostalTownTextBox.Text, value) Then
                Me.PostalTownTextBox.Text = value
                'Dim ppe As PropertyChangedEventArgs = New PropertyChangedEventArgs("PostalTown")
                'OnValueChanged(ppe)
            End If
        End Set
    End Property
    <System.ComponentModel.Bindable(True, BindingDirection.TwoWay)>
    Public Property County As String
        Get
            Return Me.CountyTextBox.Text
        End Get
        Set(ByVal value As String)
            If Not Equals(Me.CountyTextBox.Text, value) Then
                Me.CountyTextBox.Text = value
                'Dim ppe As PropertyChangedEventArgs = New PropertyChangedEventArgs("County")
                'OnValueChanged(ppe)
            End If

        End Set
    End Property
    <System.ComponentModel.Bindable(True, BindingDirection.TwoWay)>
    Public Property PostCode As String
        Get
            Return Me.PostCodeTextBox1.Postcode
        End Get
        Set(ByVal value As String)
            If Not Equals(Me.PostCodeTextBox1.Postcode, value) Then
                Me.PostCodeTextBox1.Postcode = value
                'Dim ppe As PropertyChangedEventArgs = New PropertyChangedEventArgs("PostCode")
                'OnValueChanged(ppe)
            End If

        End Set
    End Property
    <System.ComponentModel.Bindable(True, BindingDirection.TwoWay)>
    Public Property CountryCode As String
        Get
            Return Me.CountryDropDownList1.CountryCode
        End Get
        Set(ByVal value As String)
            If Not Equals(Me.CountryDropDownList1.CountryCode, value) Then
                Me.CountryDropDownList1.CountryCode = value
                CountryName = CountryDropDownList1.CountryName
                CountryNameAndCode = CountryDropDownList1.CountryNameAndCode
                AreaOfWorld = CountryDropDownList1.AreaOfWorld
                'Dim ppe As PropertyChangedEventArgs = New PropertyChangedEventArgs("CountryCode")
                'OnValueChanged(ppe)
            End If

        End Set
    End Property
    Public Sub OnValueChanged(ByVal e As System.ComponentModel.PropertyChangedEventArgs)
        RaiseEvent ValueChanged(Me, e)
    End Sub

    Private _readOnlyAddress As Boolean = False
    <Category("Appearance")>
    Public Property ReadOnlyAddress As Boolean
        Get
            Return _readOnlyAddress
        End Get
        Set(ByVal value As Boolean)
            _readOnlyAddress = value

            If value = True Then
                Me.BusinessNameTextBox.ReadOnly = True
                Me.AddressLine1TextBox.ReadOnly = True
                Me.AddressLine2TextBox.ReadOnly = True
                Me.AddressLine3TextBox.ReadOnly = True
                Me.PostalTownTextBox.ReadOnly = True
                Me.CountyTextBox.ReadOnly = True
                Me.PostalTownTextBox.ReadOnly = True
                Me.CountryDropDownList1.Enabled = False
                Me.PostCodeTextBox1.RadTextBoxPostcode.ReadOnly = True
                Me.PostCodeTextBox1.RadButtonFind.Enabled = False
            Else
                Me.BusinessNameTextBox.ReadOnly = False
                Me.AddressLine1TextBox.ReadOnly = False
                Me.AddressLine2TextBox.ReadOnly = False
                Me.AddressLine3TextBox.ReadOnly = False
                Me.PostalTownTextBox.ReadOnly = False
                Me.CountyTextBox.ReadOnly = False
                Me.PostalTownTextBox.ReadOnly = False
                Me.CountryDropDownList1.Enabled = True
                Me.PostCodeTextBox1.RadTextBoxPostcode.ReadOnly = False
                Me.PostCodeTextBox1.RadButtonFind.Enabled = True
            End If
            ReadOnlyEvent()
        End Set
    End Property

    Private Sub ReadOnlyEvent()
        For Each control In Me.Controls
            If (TypeOf control Is Telerik.WinControls.UI.RadTextBox) Then
                If control.ReadOnly = True Then
                    control.ForeColor = Color.Gray
                Else
                    control.ForeColor = Color.Black
                End If
            End If
        Next
    End Sub

End Class

Open in new window

Commented:
Is there a Designer file?  The code you posted is missing the declaration and initialization of the controls that make up the custom control.

-saige-

Author

Commented:
In the below I have simplified it as much as possible and still getting the issue. All I do is add the control below to a form, then under binding set the bussiness and address line 1.
When I close the form it says data has changed.

the 2 files are below. (I have also used normal textboxes just incase it was an error with telerik controls, plus even commented out the OnValueChanged)

testcontrol.Designer.vb
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class testcontrol
    Inherits System.Windows.Forms.UserControl

    'UserControl overrides dispose to clean up the component list.
    <System.Diagnostics.DebuggerNonUserCode()> _
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        Try
            If disposing AndAlso components IsNot Nothing Then
                components.Dispose()
            End If
        Finally
            MyBase.Dispose(disposing)
        End Try
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    <System.Diagnostics.DebuggerStepThrough()> _
    Private Sub InitializeComponent()
        Me.BusinessNameTextBox1 = New System.Windows.Forms.TextBox()
        Me.AddressLine1TextBox1 = New System.Windows.Forms.TextBox()
        Me.Label1 = New System.Windows.Forms.Label()
        Me.Label2 = New System.Windows.Forms.Label()
        Me.SuspendLayout()
        '
        'BusinessNameTextBox1
        '
        Me.BusinessNameTextBox1.Anchor = CType(((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Left) _
            Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
        Me.BusinessNameTextBox1.Location = New System.Drawing.Point(78, 3)
        Me.BusinessNameTextBox1.Name = "BusinessNameTextBox1"
        Me.BusinessNameTextBox1.Size = New System.Drawing.Size(212, 26)
        Me.BusinessNameTextBox1.TabIndex = 173
        '
        'AddressLine1TextBox1
        '
        Me.AddressLine1TextBox1.Anchor = CType(((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Left) _
            Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
        Me.AddressLine1TextBox1.Location = New System.Drawing.Point(78, 35)
        Me.AddressLine1TextBox1.Name = "AddressLine1TextBox1"
        Me.AddressLine1TextBox1.Size = New System.Drawing.Size(212, 26)
        Me.AddressLine1TextBox1.TabIndex = 173
        '
        'Label1
        '
        Me.Label1.AutoSize = True
        Me.Label1.Location = New System.Drawing.Point(3, 6)
        Me.Label1.Name = "Label1"
        Me.Label1.Size = New System.Drawing.Size(51, 20)
        Me.Label1.TabIndex = 174
        Me.Label1.Text = "Name"
        '
        'Label2
        '
        Me.Label2.AutoSize = True
        Me.Label2.Location = New System.Drawing.Point(3, 38)
        Me.Label2.Name = "Label2"
        Me.Label2.Size = New System.Drawing.Size(68, 20)
        Me.Label2.TabIndex = 175
        Me.Label2.Text = "Address"
        '
        'testcontrol
        '
        Me.AutoScaleDimensions = New System.Drawing.SizeF(9.0!, 20.0!)
        Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
        Me.Controls.Add(Me.Label2)
        Me.Controls.Add(Me.Label1)
        Me.Controls.Add(Me.AddressLine1TextBox1)
        Me.Controls.Add(Me.BusinessNameTextBox1)
        Me.Name = "testcontrol"
        Me.Size = New System.Drawing.Size(293, 67)
        Me.ResumeLayout(False)
        Me.PerformLayout()

    End Sub
    Friend WithEvents BusinessNameTextBox1 As Windows.Forms.TextBox
    Friend WithEvents AddressLine1TextBox1 As Windows.Forms.TextBox
    Friend WithEvents Label1 As Windows.Forms.Label
    Friend WithEvents Label2 As Windows.Forms.Label
End Class

Open in new window


testcontrol.vb
Imports System.ComponentModel
Imports System.Drawing
Imports System.Windows.Forms
Public Class testcontrol
    <System.ComponentModel.Bindable(True, BindingDirection.TwoWay)>
    Public Property BusinessName As String
        Get
            Return Me.BusinessNameTextBox1.Text
        End Get
        Set(ByVal value As String)
            If Not Equals(Me.BusinessNameTextBox1.Text, value) Then
                Me.BusinessNameTextBox1.Text = value
                'Dim ppe As PropertyChangedEventArgs = New PropertyChangedEventArgs("BusinessName")
                'OnValueChanged(ppe)
            End If

        End Set
    End Property

    <System.ComponentModel.Bindable(True, BindingDirection.TwoWay)>
    Public Property AddressLine1 As String
        Get
            Return Me.AddressLine1TextBox1.Text
        End Get
        Set(ByVal value As String)
            If Not Equals(Me.AddressLine1TextBox1.Text, value) Then
                Me.AddressLine1TextBox1.Text = value
                'Dim ppe As PropertyChangedEventArgs = New PropertyChangedEventArgs("AddressLine1")
                'OnValueChanged(ppe)
            End If

        End Set
    End Property
End Class

Open in new window

Commented:
Assuming that all you want to do is implement two-way binding, you should really only need something like this:

BusinessAddress.vb -
Public Class BusinessAddress
    Public Property BusinessName As String
    Public Property AddressLine1 As String
End Class

Open in new window

Form1.vb -
Imports System.ComponentModel

Public Class Form1
    Private isLoading As Boolean
    Private _businessAddress As BusinessAddress

    Private Sub OnLoad(sender As Object, e As EventArgs) Handles MyBase.Load
        isLoading = True
        _businessAddress = New BusinessAddress With
        {
            .BusinessName = "Test Business",
            .AddressLine1 = "Test Address Line 1"
        }

        TestControl1.DataBindings.Add(New Binding(NameOf(TestControl1.BusinessName), _businessAddress, NameOf(BusinessAddress.BusinessName), True, DataSourceUpdateMode.OnPropertyChanged))
        TestControl1.DataBindings.Add(New Binding(NameOf(TestControl1.AddressLine1), _businessAddress, NameOf(BusinessAddress.AddressLine1), True, DataSourceUpdateMode.OnPropertyChanged))

        isLoading = False
    End Sub

    Private Sub OnValueChanged(sender As Object, e As PropertyChangedEventArgs)
        If Not isLoading Then
            Select Case e.PropertyName
                Case NameOf(TestControl1.BusinessName)
                    MessageBox.Show($"{e.PropertyName} has changed: {TestControl1.BusinessName}")
                Case NameOf(TestControl1.AddressLine1)
                    MessageBox.Show($"{e.PropertyName} has changed: {TestControl1.AddressLine1}")
            End Select
        End If
    End Sub

    Private Sub OnClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
        MessageBox.Show($"{NameOf(BusinessAddress.BusinessName)}: {_businessAddress.BusinessName}{Environment.NewLine}{NameOf(BusinessAddress.AddressLine1)}: {_businessAddress.AddressLine1}")
    End Sub
End Class

Open in new window

Form1.Designer.vb -
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
Partial Class Form1
    Inherits System.Windows.Forms.Form

    'Form overrides dispose to clean up the component list.
    <System.Diagnostics.DebuggerNonUserCode()>
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        Try
            If disposing AndAlso components IsNot Nothing Then
                components.Dispose()
            End If
        Finally
            MyBase.Dispose(disposing)
        End Try
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    <System.Diagnostics.DebuggerStepThrough()>
    Private Sub InitializeComponent()
        Me.TestControl1 = New EE_Q29168238.TestControl()
        Me.SuspendLayout()
        '
        'TestControl1
        '
        Me.TestControl1.AddressLine1 = ""
        Me.TestControl1.BusinessName = ""
        Me.TestControl1.Location = New System.Drawing.Point(13, 13)
        Me.TestControl1.Margin = New System.Windows.Forms.Padding(2)
        Me.TestControl1.Name = "TestControl1"
        Me.TestControl1.Size = New System.Drawing.Size(195, 44)
        Me.TestControl1.TabIndex = 0
        '
        'Form1
        '
        Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
        Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
        Me.ClientSize = New System.Drawing.Size(236, 72)
        Me.Controls.Add(Me.TestControl1)
        Me.Name = "Form1"
        Me.Text = "Form1"
        Me.ResumeLayout(False)

    End Sub

    Friend WithEvents TestControl1 As TestControl
End Class

Open in new window

TestControl.vb -
Imports System.ComponentModel

Public Class TestControl
    <Bindable(BindableSupport.Yes, BindingDirection.TwoWay)>
    Public Property BusinessName() As String

    <Bindable(BindableSupport.Yes, BindingDirection.TwoWay)>
    Public Property AddressLine1() As String

    Public Sub New()
        InitializeComponent()

        BusinessNameTextBox1.DataBindings.Add(New Binding("Text", Me, NameOf(BusinessName), True, DataSourceUpdateMode.OnPropertyChanged))
        AddressLine1TextBox1.DataBindings.Add(New Binding("Text", Me, NameOf(AddressLine1), True, DataSourceUpdateMode.OnPropertyChanged))
    End Sub
End Class

Open in new window

TestControl.Designer.vb -
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class TestControl
    Inherits System.Windows.Forms.UserControl

    'UserControl overrides dispose to clean up the component list.
    <System.Diagnostics.DebuggerNonUserCode()>
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        Try
            If disposing AndAlso components IsNot Nothing Then
                components.Dispose()
            End If
        Finally
            MyBase.Dispose(disposing)
        End Try
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    <System.Diagnostics.DebuggerStepThrough()>
    Private Sub InitializeComponent()
        Me.BusinessNameTextBox1 = New System.Windows.Forms.TextBox()
        Me.AddressLine1TextBox1 = New System.Windows.Forms.TextBox()
        Me.Label1 = New System.Windows.Forms.Label()
        Me.Label2 = New System.Windows.Forms.Label()
        Me.SuspendLayout()
        '
        'BusinessNameTextBox1
        '
        Me.BusinessNameTextBox1.Anchor = CType(((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Left) _
            Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
        Me.BusinessNameTextBox1.Location = New System.Drawing.Point(52, 2)
        Me.BusinessNameTextBox1.Margin = New System.Windows.Forms.Padding(2, 2, 2, 2)
        Me.BusinessNameTextBox1.Name = "BusinessNameTextBox1"
        Me.BusinessNameTextBox1.Size = New System.Drawing.Size(143, 20)
        Me.BusinessNameTextBox1.TabIndex = 173
        '
        'AddressLine1TextBox1
        '
        Me.AddressLine1TextBox1.Anchor = CType(((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Left) _
            Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
        Me.AddressLine1TextBox1.Location = New System.Drawing.Point(52, 23)
        Me.AddressLine1TextBox1.Margin = New System.Windows.Forms.Padding(2, 2, 2, 2)
        Me.AddressLine1TextBox1.Name = "AddressLine1TextBox1"
        Me.AddressLine1TextBox1.Size = New System.Drawing.Size(143, 20)
        Me.AddressLine1TextBox1.TabIndex = 173
        '
        'Label1
        '
        Me.Label1.AutoSize = True
        Me.Label1.Location = New System.Drawing.Point(2, 4)
        Me.Label1.Margin = New System.Windows.Forms.Padding(2, 0, 2, 0)
        Me.Label1.Name = "Label1"
        Me.Label1.Size = New System.Drawing.Size(35, 13)
        Me.Label1.TabIndex = 174
        Me.Label1.Text = "Name"
        '
        'Label2
        '
        Me.Label2.AutoSize = True
        Me.Label2.Location = New System.Drawing.Point(2, 25)
        Me.Label2.Margin = New System.Windows.Forms.Padding(2, 0, 2, 0)
        Me.Label2.Name = "Label2"
        Me.Label2.Size = New System.Drawing.Size(45, 13)
        Me.Label2.TabIndex = 175
        Me.Label2.Text = "Address"
        '
        'TestControl
        '
        Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
        Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
        Me.Controls.Add(Me.Label2)
        Me.Controls.Add(Me.Label1)
        Me.Controls.Add(Me.AddressLine1TextBox1)
        Me.Controls.Add(Me.BusinessNameTextBox1)
        Me.Margin = New System.Windows.Forms.Padding(2, 2, 2, 2)
        Me.Name = "TestControl"
        Me.Size = New System.Drawing.Size(195, 44)
        Me.ResumeLayout(False)
        Me.PerformLayout()
    End Sub

    Friend WithEvents BusinessNameTextBox1 As Windows.Forms.TextBox
    Friend WithEvents AddressLine1TextBox1 As Windows.Forms.TextBox
    Friend WithEvents Label1 As Windows.Forms.Label
    Friend WithEvents Label2 As Windows.Forms.Label
End Class

Open in new window

Which produces the following output -Initial LoadAfter modifying the fieldsBound object on the main form is updatedForm closing messageHTH,

-saige-

Author

Commented:
I thanks I tried what you said but still getting same issue. Using your idea this is what I have now, but still getting same issue.

When I say bindingsoucre.endedit when the form is closing it thinks something has changed. I really want to simplify it as much as possible as I will be using it on lots of forms.

TestControl.vb
Imports System.ComponentModel
Imports System.Windows.Forms

Public Class TestControl
    <Bindable(BindableSupport.Yes, BindingDirection.TwoWay)>
    Public Property BusinessName() As String

    <Bindable(BindableSupport.Yes, BindingDirection.TwoWay)>
    Public Property AddressLine1() As String

    Public Sub New()
        InitializeComponent()

        BusinessNameTextBox1.DataBindings.Add(New Binding("Text", Me, NameOf(BusinessName), True, DataSourceUpdateMode.OnPropertyChanged))
        AddressLine1TextBox1.DataBindings.Add(New Binding("Text", Me, NameOf(AddressLine1), True, DataSourceUpdateMode.OnPropertyChanged))
    End Sub
End Class

Open in new window


testcontrol.designer.vb
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
Partial Class TestControl
    Inherits System.Windows.Forms.UserControl

    'UserControl overrides dispose to clean up the component list.
    <System.Diagnostics.DebuggerNonUserCode()>
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        Try
            If disposing AndAlso components IsNot Nothing Then
                components.Dispose()
            End If
        Finally
            MyBase.Dispose(disposing)
        End Try
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    <System.Diagnostics.DebuggerStepThrough()>
    Private Sub InitializeComponent()
        Me.BusinessNameTextBox1 = New System.Windows.Forms.TextBox()
        Me.AddressLine1TextBox1 = New System.Windows.Forms.TextBox()
        Me.Label1 = New System.Windows.Forms.Label()
        Me.Label2 = New System.Windows.Forms.Label()
        Me.SuspendLayout()
        '
        'BusinessNameTextBox1
        '
        Me.BusinessNameTextBox1.Anchor = CType(((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Left) _
            Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
        Me.BusinessNameTextBox1.Location = New System.Drawing.Point(104, 0)
        Me.BusinessNameTextBox1.Name = "BusinessNameTextBox1"
        Me.BusinessNameTextBox1.Size = New System.Drawing.Size(185, 26)
        Me.BusinessNameTextBox1.TabIndex = 173
        '
        'AddressLine1TextBox1
        '
        Me.AddressLine1TextBox1.Anchor = CType(((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Left) _
            Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
        Me.AddressLine1TextBox1.Location = New System.Drawing.Point(104, 32)
        Me.AddressLine1TextBox1.Name = "AddressLine1TextBox1"
        Me.AddressLine1TextBox1.Size = New System.Drawing.Size(185, 26)
        Me.AddressLine1TextBox1.TabIndex = 173
        '
        'Label1
        '
        Me.Label1.AutoSize = True
        Me.Label1.Location = New System.Drawing.Point(3, 6)
        Me.Label1.Name = "Label1"
        Me.Label1.Size = New System.Drawing.Size(96, 30)
        Me.Label1.TabIndex = 174
        Me.Label1.Text = "Name 1"
        '
        'Label2
        '
        Me.Label2.AutoSize = True
        Me.Label2.Location = New System.Drawing.Point(3, 38)
        Me.Label2.Name = "Label2"
        Me.Label2.Size = New System.Drawing.Size(68, 20)
        Me.Label2.TabIndex = 175
        Me.Label2.Text = "Address"
        '
        'TestControl
        '
        Me.AutoScaleDimensions = New System.Drawing.SizeF(9.0!, 20.0!)
        Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
        Me.Controls.Add(Me.Label2)
        Me.Controls.Add(Me.Label1)
        Me.Controls.Add(Me.AddressLine1TextBox1)
        Me.Controls.Add(Me.BusinessNameTextBox1)
        Me.Name = "TestControl"
        Me.Size = New System.Drawing.Size(292, 173)
        Me.ResumeLayout(False)
        Me.PerformLayout()

    End Sub

    Friend WithEvents BusinessNameTextBox1 As Windows.Forms.TextBox
    Friend WithEvents AddressLine1TextBox1 As Windows.Forms.TextBox
    Friend WithEvents Label1 As Windows.Forms.Label
    Friend WithEvents Label2 As Windows.Forms.Label
End Class

Open in new window


testsupplierform.vb
Public Class Testsupplierform

    Private Sub Testsupplierform_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
        Try
            Me.SuppliersBindingSource.EndEdit()
        Catch ex As Exception
        End Try
        If Me.SuppliersDataSet1.HasChanges Then
            If Telerik.WinControls.RadMessageBox.Show(MainFormOpen, "Would you like to save changes?", "Warning", MessageBoxButtons.YesNo, Telerik.WinControls.RadMessageIcon.Question) = vbYes Then
                ' SaveData()
            End If
        End If
    End Sub

    Public Sub LoadSupplierID(SupplierID As String)
        Me.SuppliersTableAdapter.FillBySupplierID(Me.SuppliersDataSet1.Suppliers, SupplierID)
    End Sub
End Class

Open in new window



testsupplierform.designer.vb
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class Testsupplierform
    Inherits Telerik.WinControls.UI.RadForm

    'Form overrides dispose to clean up the component list.
    <System.Diagnostics.DebuggerNonUserCode()> _
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        Try
            If disposing AndAlso components IsNot Nothing Then
                components.Dispose()
            End If
        Finally
            MyBase.Dispose(disposing)
        End Try
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    <System.Diagnostics.DebuggerStepThrough()> _
    Private Sub InitializeComponent()
        Me.components = New System.ComponentModel.Container()
        Me.SuppliersDataSet1 = New TestApp.SuppliersDataSet()
        Me.SuppliersBindingSource = New System.Windows.Forms.BindingSource(Me.components)
        Me.SuppliersTableAdapter = New TestApp.SuppliersDataSetTableAdapters.SuppliersTableAdapter()
        Me.TestControl1 = New AdvantaCrontrols.TestControl()
        CType(Me.SuppliersDataSet1, System.ComponentModel.ISupportInitialize).BeginInit()
        CType(Me.SuppliersBindingSource, System.ComponentModel.ISupportInitialize).BeginInit()
        CType(Me, System.ComponentModel.ISupportInitialize).BeginInit()
        Me.SuspendLayout()
        '
        'SuppliersDataSet1
        '
        Me.SuppliersDataSet1.DataSetName = "SuppliersDataSet"
        Me.SuppliersDataSet1.SchemaSerializationMode = System.Data.SchemaSerializationMode.IncludeSchema
        '
        'SuppliersBindingSource
        '
        Me.SuppliersBindingSource.DataMember = "Suppliers"
        Me.SuppliersBindingSource.DataSource = Me.SuppliersDataSet1
        '
        'SuppliersTableAdapter
        '
        Me.SuppliersTableAdapter.ClearBeforeFill = True
        '
        'TestControl1
        '
        Me.TestControl1.AddressLine1 = Nothing
        Me.TestControl1.BusinessName = Nothing

        Me.TestControl1.DataBindings.Add(New System.Windows.Forms.Binding("AddressLine1", Me.SuppliersBindingSource, "AddressLine1", True))
        Me.TestControl1.DataBindings.Add(New System.Windows.Forms.Binding("BusinessName", Me.SuppliersBindingSource, "BusinessName", True))
        Me.TestControl1.Location = New System.Drawing.Point(163, 123)
        Me.TestControl1.Name = "TestControl1"
        Me.TestControl1.Size = New System.Drawing.Size(292, 173)
        Me.TestControl1.TabIndex = 0
        '
        'Testsupplierform
        '
        Me.AutoScaleDimensions = New System.Drawing.SizeF(9.0!, 20.0!)
        Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
        Me.ClientSize = New System.Drawing.Size(814, 466)
        Me.Controls.Add(Me.TestControl1)
        Me.Name = "Testsupplierform"
        '
        '
        '
        Me.RootElement.ApplyShapeToControl = True
        Me.Text = "Testsupplierform"
        CType(Me.SuppliersDataSet1, System.ComponentModel.ISupportInitialize).EndInit()
        CType(Me.SuppliersBindingSource, System.ComponentModel.ISupportInitialize).EndInit()
        CType(Me, System.ComponentModel.ISupportInitialize).EndInit()
        Me.ResumeLayout(False)

    End Sub
    Friend WithEvents SuppliersDataSet1 As SuppliersDataSet
    Friend WithEvents SuppliersBindingSource As BindingSource
    Friend WithEvents SuppliersTableAdapter As SuppliersDataSetTableAdapters.SuppliersTableAdapter
    Friend WithEvents TestControl1 As AdvantaCrontrols.TestControl
End Class

Open in new window

Commented:
Understand that when you first bind your data source to the BindingSource, it is changed. What you need to do then is to Accept the initial changes.

BindingSource has a BindingComplete event that we can use in order to end the edits caused by the loading of the form.  This, though, presents a problem because the BindingComplete event fires when the form closes, which would cause another EndEdit (even if we did not change the data).  To combat this, we must clone the DataRow and Compare the clone to the row in the DataSet before calling the final EndEdit in our OnClosing event:

TestControl.vb -
Imports System.ComponentModel

Public Class TestControl
    <Bindable(BindableSupport.Yes, BindingDirection.TwoWay)>
    Public Property BusinessName() As String

    <Bindable(BindableSupport.Yes, BindingDirection.TwoWay)>
    Public Property AddressLine1() As String

    Public Sub New()
        InitializeComponent()

        BusinessNameTextBox1.DataBindings.Add(New Binding("Text", Me, NameOf(BusinessName), True, DataSourceUpdateMode.OnPropertyChanged))
        AddressLine1TextBox1.DataBindings.Add(New Binding("Text", Me, NameOf(AddressLine1), True, DataSourceUpdateMode.OnPropertyChanged))
    End Sub
End Class

Open in new window

TestControl.Designer.vb -
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class TestControl
    Inherits System.Windows.Forms.UserControl

    'UserControl overrides dispose to clean up the component list.
    <System.Diagnostics.DebuggerNonUserCode()>
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        Try
            If disposing AndAlso components IsNot Nothing Then
                components.Dispose()
            End If
        Finally
            MyBase.Dispose(disposing)
        End Try
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    <System.Diagnostics.DebuggerStepThrough()>
    Private Sub InitializeComponent()
        Me.BusinessNameTextBox1 = New System.Windows.Forms.TextBox()
        Me.AddressLine1TextBox1 = New System.Windows.Forms.TextBox()
        Me.Label1 = New System.Windows.Forms.Label()
        Me.Label2 = New System.Windows.Forms.Label()
        Me.SuspendLayout()
        '
        'BusinessNameTextBox1
        '
        Me.BusinessNameTextBox1.Anchor = CType(((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Left) _
            Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
        Me.BusinessNameTextBox1.Location = New System.Drawing.Point(52, 2)
        Me.BusinessNameTextBox1.Margin = New System.Windows.Forms.Padding(2, 2, 2, 2)
        Me.BusinessNameTextBox1.Name = "BusinessNameTextBox1"
        Me.BusinessNameTextBox1.Size = New System.Drawing.Size(143, 20)
        Me.BusinessNameTextBox1.TabIndex = 173
        '
        'AddressLine1TextBox1
        '
        Me.AddressLine1TextBox1.Anchor = CType(((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Left) _
            Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
        Me.AddressLine1TextBox1.Location = New System.Drawing.Point(52, 23)
        Me.AddressLine1TextBox1.Margin = New System.Windows.Forms.Padding(2, 2, 2, 2)
        Me.AddressLine1TextBox1.Name = "AddressLine1TextBox1"
        Me.AddressLine1TextBox1.Size = New System.Drawing.Size(143, 20)
        Me.AddressLine1TextBox1.TabIndex = 173
        '
        'Label1
        '
        Me.Label1.AutoSize = True
        Me.Label1.Location = New System.Drawing.Point(2, 4)
        Me.Label1.Margin = New System.Windows.Forms.Padding(2, 0, 2, 0)
        Me.Label1.Name = "Label1"
        Me.Label1.Size = New System.Drawing.Size(35, 13)
        Me.Label1.TabIndex = 174
        Me.Label1.Text = "Name"
        '
        'Label2
        '
        Me.Label2.AutoSize = True
        Me.Label2.Location = New System.Drawing.Point(2, 25)
        Me.Label2.Margin = New System.Windows.Forms.Padding(2, 0, 2, 0)
        Me.Label2.Name = "Label2"
        Me.Label2.Size = New System.Drawing.Size(45, 13)
        Me.Label2.TabIndex = 175
        Me.Label2.Text = "Address"
        '
        'TestControl
        '
        Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
        Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
        Me.Controls.Add(Me.Label2)
        Me.Controls.Add(Me.Label1)
        Me.Controls.Add(Me.AddressLine1TextBox1)
        Me.Controls.Add(Me.BusinessNameTextBox1)
        Me.Margin = New System.Windows.Forms.Padding(2, 2, 2, 2)
        Me.Name = "TestControl"
        Me.Size = New System.Drawing.Size(195, 44)
        Me.ResumeLayout(False)
        Me.PerformLayout()
    End Sub

    Friend WithEvents BusinessNameTextBox1 As Windows.Forms.TextBox
    Friend WithEvents AddressLine1TextBox1 As Windows.Forms.TextBox
    Friend WithEvents Label1 As Windows.Forms.Label
    Friend WithEvents Label2 As Windows.Forms.Label
End Class

Open in new window

Form1.vb -
Imports System.Runtime.CompilerServices

Public Class Form1
    Private isLoading As Boolean
    Private current As DataTable

    Private Sub OnLoad(sender As Object, e As EventArgs) Handles MyBase.Load
        isLoading = True

        LoadSupplier(1)

        current = SuppliersDataSet1.Suppliers.Clone()
        current.ImportRow(SuppliersDataSet1.Suppliers(0))

        TestControl1.DataBindings.Add(New Binding(NameOf(TestControl1.BusinessName), SuppliersBindingSource, NameOf(TestControl1.BusinessName), True, DataSourceUpdateMode.OnPropertyChanged))
        TestControl1.DataBindings.Add(New Binding(NameOf(TestControl1.AddressLine1), SuppliersBindingSource, NameOf(TestControl1.AddressLine1), True, DataSourceUpdateMode.OnPropertyChanged))

        isLoading = False
    End Sub

    Private Sub OnClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
        Dim [row] = CType(SuppliersBindingSource.Current, DataRowView).Row
        If Not CompareTo([row], current(0)) Then
            SuppliersBindingSource.EndEdit()
        End If

        If SuppliersDataSet1.HasChanges Then
            Select Case [row].RowState
                Case DataRowState.Added
                    MessageBox.Show($"New row has been added:{Environment.NewLine}{NameOf(TestControl1.BusinessName)}: {row("BusinessName")}{Environment.NewLine}{NameOf(TestControl1.AddressLine1)}: {row("AddressLine1")}")
                    Exit Select
                Case DataRowState.Deleted
                    MessageBox.Show("Row was deleted")
                    Exit Select
                Case DataRowState.Modified
                    MessageBox.Show($"Row has been modified:{Environment.NewLine}{NameOf(TestControl1.BusinessName)}: {row("BusinessName")}{Environment.NewLine}{NameOf(TestControl1.AddressLine1)}: {row("AddressLine1")}")
                    Exit Select
            End Select
        Else
            MessageBox.Show($"Row has not been modified:{Environment.NewLine}{NameOf(TestControl1.BusinessName)}: {row("BusinessName")}{Environment.NewLine}{NameOf(TestControl1.AddressLine1)}: {row("AddressLine1")}")
        End If
    End Sub

    Public Sub LoadSupplier(SupplierId As Integer)
        SuppliersTableAdapter.FillBySupplierId(SuppliersDataSet1.Suppliers, SupplierId)
    End Sub

    Private Sub OnBindingComplete(sender As Object, e As BindingCompleteEventArgs) Handles SuppliersBindingSource.BindingComplete
        If isLoading Then
            Dim binder = CType(sender, BindingSource)
            binder.EndEdit()
            CType(binder.DataSource, DataSet).AcceptChanges()
        End If
    End Sub
End Class

Module Extensions
    <Extension>
    Public Function CompareTo(lhs As DataRow, rhs As DataRow) As Boolean
        If ReferenceEquals(lhs, Nothing) OrElse ReferenceEquals(rhs, Nothing) Then Return False
        If ReferenceEquals(lhs, rhs) Then Return True
        If Not Equals(lhs.ItemArray.Length, rhs.ItemArray.Length) Then Return False

        For i = 0 To lhs.ItemArray.Length - 1
            If Not Equals(lhs(i), rhs(i)) Then Return False
        Next

        Return True
    End Function

    <Extension>
    Public Function CompareTo(lhs As DataTable, rhs As DataTable) As Boolean
        If ReferenceEquals(lhs, Nothing) OrElse ReferenceEquals(rhs, Nothing) Then Return False
        If ReferenceEquals(lhs, rhs) Then Return True
        If Not Equals(lhs.Columns.Count, rhs.Columns.Count) Then Return False
        If Not Equals(lhs.Rows.Count, rhs.Rows.Count) Then Return False

        For i = 0 To lhs.Rows.Count - 1
            If Not CompareTo(lhs(i), rhs(i)) Then Return False
        Next

        Return True
    End Function
End Module

Open in new window

Form1.Designer.vb -
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
Partial Class Form1
    Inherits System.Windows.Forms.Form

    'Form overrides dispose to clean up the component list.
    <System.Diagnostics.DebuggerNonUserCode()>
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        Try
            If disposing AndAlso components IsNot Nothing Then
                components.Dispose()
            End If
        Finally
            MyBase.Dispose(disposing)
        End Try
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    <System.Diagnostics.DebuggerStepThrough()>
    Private Sub InitializeComponent()
        Me.components = New System.ComponentModel.Container()
        Me.SuppliersDataSet1 = New EE_Q29168238.SuppliersDataSet()
        Me.SuppliersBindingSource = New System.Windows.Forms.BindingSource(Me.components)
        Me.SuppliersTableAdapter = New EE_Q29168238.SupplierDataSetTableAdapters.SuppliersTableAdapter()
        Me.TestControl1 = New EE_Q29168238.TestControl()
        CType(Me.SuppliersDataSet1, System.ComponentModel.ISupportInitialize).BeginInit()
        CType(Me.SuppliersBindingSource, System.ComponentModel.ISupportInitialize).BeginInit()
        Me.SuspendLayout()
        '
        'SuppliersDataSet1
        '
        Me.SuppliersDataSet1.DataSetName = "SupplierDataSet"
        Me.SuppliersDataSet1.SchemaSerializationMode = System.Data.SchemaSerializationMode.IncludeSchema
        '
        'SuppliersBindingSource
        '
        Me.SuppliersBindingSource.DataMember = "Suppliers"
        Me.SuppliersBindingSource.DataSource = Me.SuppliersDataSet1
        '
        'SuppliersTableAdapter
        '
        Me.SuppliersTableAdapter.ClearBeforeFill = True
        '
        'TestControl1
        '
        Me.TestControl1.AddressLine1 = ""
        Me.TestControl1.BusinessName = ""
        Me.TestControl1.Location = New System.Drawing.Point(13, 13)
        Me.TestControl1.Margin = New System.Windows.Forms.Padding(2)
        Me.TestControl1.Name = "TestControl1"
        Me.TestControl1.Size = New System.Drawing.Size(195, 44)
        Me.TestControl1.TabIndex = 0
        '
        'Form1
        '
        Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
        Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
        Me.ClientSize = New System.Drawing.Size(236, 72)
        Me.Controls.Add(Me.TestControl1)
        Me.Name = "Form1"
        Me.Text = "Form1"
        CType(Me.SuppliersDataSet1, System.ComponentModel.ISupportInitialize).EndInit()
        CType(Me.SuppliersBindingSource, System.ComponentModel.ISupportInitialize).EndInit()
        Me.ResumeLayout(False)

    End Sub

    Friend WithEvents TestControl1 As TestControl
    Friend WithEvents SuppliersDataSet1 As SuppliersDataSet
    Friend WithEvents SuppliersBindingSource As BindingSource
    Friend WithEvents SuppliersTableAdapter As SupplierDataSetTableAdapters.SuppliersTableAdapter
End Class

Open in new window

HTH,

-saige-

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial