locked
binding class property to datatable? RRS feed

  • Question

  • Hallo,

    previously i had a property not inside of a class and i used to bind to a datatable in a following way

    Form1.DataBindings.Add("Name", Contact_BS, dtName, True, DataSourceUpdateMode.OnPropertyChanged)

     Where , Name is a public property and Contact_BS is a binding source of the data table contact, dtName is column in a data table contact.

    Now i have a class called contact and want to bind Name in contact class to the data table. I have tried following but i am getting error.

    Public Contacts as Contact
    
    Public Class Contact
    
            Private _Name As String
            Private _Ph As Integer
    
    Public Property Name As String
                Get
                    Return _Name
                End Get
                Set
                    _Name = Value
                    OnPropertyChanged()
                End Set
    End Property
    
    Public Property Ph As integer
                Get
                    Return _Ph
                End Get
                Set
                    _Ph = Value
                    OnPropertyChanged()
                End Set
    End Property
    
    
    End class
    
    
    Form1.DataBindings.Add("Contacts.Name", Contact_BS, dtName, True, DataSourceUpdateMode.OnPropertyChanged)

    Thanks

     
    Wednesday, May 6, 2020 11:36 AM

Answers

  • Hi Shan1986,

    >>Form1.DataBindings.Add("Contacts.Name", Contact_BS, dtName, True, DataSourceUpdateMode.OnPropertyChanged)

    You cannot bind 'Contacts.Name' to your Form1.DataBindings, the property must be one of the properties in Form1, such as 'Name', 'Text' , etc.

    The following document contains some examples of how to use ControlBindingsCollection.Add Method.

    ControlBindingsCollection.Add Method

    If you want to get the datatable based on the value in your class property, reflection is a good choice, and you can refer to the 'ToDataTable' function in my previous reply.

    Best Regards,

    Xingyu Zhao


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • Marked as answer by Shan1986 Monday, May 11, 2020 12:34 PM
    Monday, May 11, 2020 8:06 AM

All replies

  • Hello,

    What is the exact error and on what line. Also, does the project compile? I ask about can you compile because it appears that thee is OnPropertyChanged without INotifyPropertyChanged event and override e.g.

    Public Event PropertyChanged As PropertyChangedEventHandler _
    	Implements INotifyPropertyChanged.PropertyChanged
    
    Protected Overridable Sub OnPropertyChanged(
    	<CallerMemberName> Optional memberName As String = Nothing)
    
    	RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(memberName))
    
    End Sub
    

    Also, I'm not seeing an overload for your implementation of DataBinding.Add as per the docs

    https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.controlbindingscollection.add?view=netcore-3.1


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    Wednesday, May 6, 2020 1:10 PM
  • Hello,

    What is the exact error and on what line. Also, does the project compile? I ask about can you compile because it appears that thee is OnPropertyChanged without INotifyPropertyChanged event and override e.g.

    Public Event PropertyChanged As PropertyChangedEventHandler _
    	Implements INotifyPropertyChanged.PropertyChanged
    
    Protected Overridable Sub OnPropertyChanged(
    	<CallerMemberName> Optional memberName As String = Nothing)
    
    	RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(memberName))
    
    End Sub

    Also, I'm not seeing an overload for your implementation of DataBinding.Add as per the docs

    https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.controlbindingscollection.add?view=netcore-3.1


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    I have implemented OnPropertyChanged and inotifyproperty changed. Project wont compile because i have error exactly on datbindings.add line .

    System.ArgumentException: 'Cannot bind to the property '"Contacts.Name"' on the target control.
    Parameter name: PropertyName

    Wednesday, May 6, 2020 3:03 PM
  • Hello,

    What is the exact error and on what line. Also, does the project compile? I ask about can you compile because it appears that thee is OnPropertyChanged without INotifyPropertyChanged event and override e.g.

    Public Event PropertyChanged As PropertyChangedEventHandler _
    	Implements INotifyPropertyChanged.PropertyChanged
    
    Protected Overridable Sub OnPropertyChanged(
    	<CallerMemberName> Optional memberName As String = Nothing)
    
    	RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(memberName))
    
    End Sub

    Also, I'm not seeing an overload for your implementation of DataBinding.Add as per the docs

    https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.controlbindingscollection.add?view=netcore-3.1


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    I have implemented OnPropertyChanged and inotifyproperty changed. Project wont compile because i have error exactly on datbindings.add line .

    System.ArgumentException: 'Cannot bind to the property '"Contacts.Name"' on the target control.
    Parameter name: PropertyName

    Okay, can't help when I don't have all the facts which I still don't have as for instance you left out part of the code in regards to what I asked before. Good luck :-)

    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    Wednesday, May 6, 2020 3:14 PM
  • Here is your simple example..

    Imports System.ComponentModel
    Imports System.Runtime.CompilerServices
    Public Class Form1
    
        Private BindingList As BindingList(Of Dog)
        Public bs As New BindingSource
        Public dogs As Dog
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    
            Dim dogs = New List(Of Dog) From {
                    New Dog() With {.Name = "Fido", .Weight = 100},
                    New Dog() With {.Name = "Pup", .Weight = 200}}
    
            BindingList = New BindingList(Of Dog)(dogs)
            ListBox1.DisplayMember = "Name"
            ListBox1.DataSource = BindingList
    
            Dim table As DataTable = GetTable()
            bs.DataSource = table
            DataGridView1.DataSource = bs
    
            Me.DataBindings.Add("dogs.Name", bs, "Name", True, DataSourceUpdateMode.OnPropertyChanged)
    
        End Sub
    
        Function GetTable() As DataTable
            ' Create new DataTable instance.
            Dim table As New DataTable
    
            ' Create four typed columns in the DataTable.
            table.Columns.Add("Name", GetType(String))
            table.Columns.Add("Weight", GetType(Integer))
    
            Return table
    
        End Function
    
    It also has the same error.
        Private Sub AddDogButton_Click(sender As Object, e As EventArgs) Handles AddDogButton.Click
            BindingList.Add(New Dog() With {.Name = "Buck", .Weight = 100})
        End Sub
    
        Private Sub ChangeNameButton_Click(sender As Object, e As EventArgs) Handles ChangeNameButton.Click
            BindingList.Item(ListBox1.SelectedIndex).Name = "New name"
        End Sub
    
        Private Sub CurrentDogWeightButton_Click(sender As Object, e As EventArgs) Handles CurrentDogIdButton.Click
            MessageBox.Show(BindingList.Item(ListBox1.SelectedIndex).Weight.ToString())
        End Sub
    
        Public Class Dog
            Implements INotifyPropertyChanged
    
            Private _name As String
            Private _weight As Integer
    
            Public Property Name As String
                Get
                    Return _name
                End Get
                Set
                    _name = Value
                    OnPropertyChanged()
                End Set
            End Property
    
            Public Property Weight As Integer
                Get
                    Return _weight
                End Get
                Set
                    _weight = Value
                    OnPropertyChanged()
                End Set
            End Property
    
            Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
            Protected Overridable Sub OnPropertyChanged(<CallerMemberName> Optional memberName As String = Nothing)
                RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(memberName))
            End Sub
    
        End Class
    
    End Class

    Wednesday, May 6, 2020 3:48 PM
  • Hi Shan1986,

    Thanks for your feedback.

    I make a test based on your code and find that 'dogs.Name' is not the property of Form1, so it causes the exception.

    You can refer to following code to correct the error:

        Function GetTable() As DataTable
            ' Create new DataTable instance.
            Dim table As New DataTable
            table.Columns.Add("Name", GetType(String))
            table.Columns.Add("Weight", GetType(Integer))
            table.Rows.Add("A", "120")
            Return table
        End Function
    
    ...
            
            Dim table As DataTable = GetTable()
            Me.DataBindings.Add("Text", table, "Name")  
    

    Besides, it seems that you don't need to add DataBindings to form1.

        Private BindingList As BindingList(Of Dog)
        Public bs As New BindingSource
        Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
            BindingList.Add(New Dog() With {.Name = "Buck", .Weight = 100})
        End Sub
        Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
            BindingList.Item(ListBox1.SelectedIndex).Name = "New name"
        End Sub
        Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
            MessageBox.Show(BindingList.Item(ListBox1.SelectedIndex).Weight.ToString())
        End Sub
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Dim dogs = New List(Of Dog) From {
                   New Dog() With {.Name = "Fido", .Weight = 100},
                   New Dog() With {.Name = "Pup", .Weight = 200}}
    
            BindingList = New BindingList(Of Dog)(dogs)
            ListBox1.DisplayMember = "Name"
            ListBox1.DataSource = BindingList
    
            bs.DataSource = BindingList
            DataGridView1.DataSource = bs
    
        End Sub
    
    ...

    Result:

    Please let me know if I have any misunderstanding.

    Best Regards,

    Xingyu Zhao


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Thursday, May 7, 2020 2:55 AM
  • Hi Shan1986,

    Thanks for your feedback.

    I make a test based on your code and find that 'dogs.Name' is not the property of Form1, so it causes the exception.

    You can refer to following code to correct the error:

        Function GetTable() As DataTable
            ' Create new DataTable instance.
            Dim table As New DataTable
            table.Columns.Add("Name", GetType(String))
            table.Columns.Add("Weight", GetType(Integer))
            table.Rows.Add("A", "120")
            Return table
        End Function
    
    ...
            
            Dim table As DataTable = GetTable()
            Me.DataBindings.Add("Text", table, "Name")  

    Besides, it seems that you don't need to add DataBindings to form1.

        Private BindingList As BindingList(Of Dog)
        Public bs As New BindingSource
        Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
            BindingList.Add(New Dog() With {.Name = "Buck", .Weight = 100})
        End Sub
        Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
            BindingList.Item(ListBox1.SelectedIndex).Name = "New name"
        End Sub
        Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
            MessageBox.Show(BindingList.Item(ListBox1.SelectedIndex).Weight.ToString())
        End Sub
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Dim dogs = New List(Of Dog) From {
                   New Dog() With {.Name = "Fido", .Weight = 100},
                   New Dog() With {.Name = "Pup", .Weight = 200}}
    
            BindingList = New BindingList(Of Dog)(dogs)
            ListBox1.DisplayMember = "Name"
            ListBox1.DataSource = BindingList
    
            bs.DataSource = BindingList
            DataGridView1.DataSource = bs
    
        End Sub
    
    ...

    Result:

    Please let me know if I have any misunderstanding.

    Best Regards,

    Xingyu Zhao


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Hallo Xingyu. thanks for the reply but my question was how to bind class property to data table. for example bind a Name property of Dog to a datatable column "Name". Thanks
    Thursday, May 7, 2020 5:00 AM
  • Hi Shan1986,

    DataTable doesn't have DataBindings property, so you cannot use .DataBindings.Add method to do that.

    Based on my research, you can consider converting List<T> to DataTable.

    Here's the code you can refer to:

        Dim table As DataTable
        Public bs As New BindingSource
        Dim dogs = New List(Of Dog) From {
                   New Dog() With {.Name = "Fido", .Weight = 100},
                   New Dog() With {.Name = "Pup", .Weight = 200}}
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            table = ToDataTable(dogs)
            bs.DataSource = table
            DataGridView1.DataSource = bs
        End Sub
        Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
            dogs.Add(New Dog() With {.Name = "Buck", .Weight = 100})
            bs.DataSource = ToDataTable(dogs)
        End Sub
        Public Shared Function ToDataTable(Of T)(ByVal data As IList(Of T)) As DataTable
            Dim properties As PropertyDescriptorCollection = TypeDescriptor.GetProperties(GetType(T))
            Dim table As DataTable = New DataTable()
    
            For Each prop As PropertyDescriptor In properties
                table.Columns.Add(prop.Name, If(Nullable.GetUnderlyingType(prop.PropertyType), prop.PropertyType))
            Next
    
            For Each item As T In data
                Dim row As DataRow = table.NewRow()
    
                For Each prop As PropertyDescriptor In properties
                    row(prop.Name) = If(prop.GetValue(item), DBNull.Value)
                Next
    
                table.Rows.Add(row)
            Next
            Return table
        End Function

    Result of my test:

    Hope it can help you.

    Best Regards,

    Xingyu Zhao

      

    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.




    Friday, May 8, 2020 1:54 AM
  • Hi Shan1986,

    DataTable doesn't have DataBindings property, so you cannot use .DataBindings.Add method to do that.

    Based on my research, you can consider converting List<T> to DataTable.

    Here's the code you can refer to:

        Dim table As DataTable
        Public bs As New BindingSource
        Dim dogs = New List(Of Dog) From {
                   New Dog() With {.Name = "Fido", .Weight = 100},
                   New Dog() With {.Name = "Pup", .Weight = 200}}
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            table = ToDataTable(dogs)
            bs.DataSource = table
            DataGridView1.DataSource = bs
        End Sub
        Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
            dogs.Add(New Dog() With {.Name = "Buck", .Weight = 100})
            bs.DataSource = ToDataTable(dogs)
        End Sub
        Public Shared Function ToDataTable(Of T)(ByVal data As IList(Of T)) As DataTable
            Dim properties As PropertyDescriptorCollection = TypeDescriptor.GetProperties(GetType(T))
            Dim table As DataTable = New DataTable()
    
            For Each prop As PropertyDescriptor In properties
                table.Columns.Add(prop.Name, If(Nullable.GetUnderlyingType(prop.PropertyType), prop.PropertyType))
            Next
    
            For Each item As T In data
                Dim row As DataRow = table.NewRow()
    
                For Each prop As PropertyDescriptor In properties
                    row(prop.Name) = If(prop.GetValue(item), DBNull.Value)
                Next
    
                table.Rows.Add(row)
            Next
            Return table
        End Function

    Result of my test:

    Hope it can help you.

    Best Regards,

    Xingyu Zhao

      

    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.




    Hallo Xingyu, I think you did not read my first post. 

    previously i had a property not inside of a class and i used to bind to a datatable in a following way

    Form1.DataBindings.Add("Name", Contact_BS, dtName, True, DataSourceUpdateMode.OnPropertyChanged)

     Where , Name is a public property and Contact_BS is a binding source of the data table contact, dtName is column in a data table contact.

    Now i have a class called contact and want to bind Name in contact class to the data table. I have tried following but i am getting error.

    Public Contacts as Contact
    
    Public Class Contact
    
            Private _Name As String
            Private _Ph As Integer
    
    Public Property Name As String
                Get
                    Return _Name
                End Get
                Set
                    _Name = Value
                    OnPropertyChanged()
                End Set
    End Property
    
    Public Property Ph As integer
                Get
                    Return _Ph
                End Get
                Set
                    _Ph = Value
                    OnPropertyChanged()
                End Set
    End Property
    
    
    End class
    
    
    Form1.DataBindings.Add("Contacts.Name", Contact_BS, dtName, True, DataSourceUpdateMode.OnPropertyChanged)


    I have a binding source for the data table and how do you bind a class property to it?

    Friday, May 8, 2020 8:59 AM


  • Hallo Xingyu, I think you did not read my first post. 


    I have a binding source for the data table and how do you bind a class property to it?

    I think he did perfectly well. He told you that you can not bind a collection to another collection. DataBinding is a feature of the Forms namespace not from Collections. But why do you need this. 

    It seems so much as the invention of bottom up dental drilling. In most countries they do it direct from the mouth, but in certain countries people are scared to do that.

    What is your reason you want such a difficult solution in which you're then alone. 


    Success
    Cor

    Friday, May 8, 2020 12:41 PM


  • Hallo Xingyu, I think you did not read my first post. 


    I have a binding source for the data table and how do you bind a class property to it?

    I think he did perfectly well. He told you that you can not bind a collection to another collection. DataBinding is a feature of the Forms namespace not from Collections. But why do you need this. 

    It seems so much as the invention of bottom up dental drilling. In most countries they do it direct from the mouth, but in certain countries people are scared to do that.

    What is your reason you want such a difficult solution in which you're then alone. 


    Success
    Cor

    Hallo Cor, thanks . i thought it should be easy as binding a property outside of class. 

    Friday, May 8, 2020 1:06 PM
  • Hi Shan1986,

    >>Form1.DataBindings.Add("Contacts.Name", Contact_BS, dtName, True, DataSourceUpdateMode.OnPropertyChanged)

    You cannot bind 'Contacts.Name' to your Form1.DataBindings, the property must be one of the properties in Form1, such as 'Name', 'Text' , etc.

    The following document contains some examples of how to use ControlBindingsCollection.Add Method.

    ControlBindingsCollection.Add Method

    If you want to get the datatable based on the value in your class property, reflection is a good choice, and you can refer to the 'ToDataTable' function in my previous reply.

    Best Regards,

    Xingyu Zhao


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • Marked as answer by Shan1986 Monday, May 11, 2020 12:34 PM
    Monday, May 11, 2020 8:06 AM