locked
Find and change specific object in a class RRS feed

  • Question

  • Hallo, 

    I have a Class called Equipments and i use the following code to add values

    Dim eList As BindingList(Of Equipments) = CType(BS.DataSource, BindingList(Of Equipments))
            eList(0).Name = ComboBox1.SelectedValue
            eList(0).Size = ComboBox2.SelectedValue
            eList(0).Cost = ComboBox3.SelectedValue

    Now i want know how can i find a specific equipment by its Name and change its value? 

    And also, How do i edit instead of using index eList(0) just edit BS.Current?

    Thanks 

    Friday, October 2, 2020 3:37 PM

Answers

  • I removed the BindingList for a ComboBox, does not make sense here.

    See this code. It's in the exact same project as before.

    • Demo's find and position
    • Change current item (can also change other than current item too but not shown)


    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

    • Marked as answer by Shan1986 Saturday, October 3, 2020 5:28 PM
    Friday, October 2, 2020 8:32 PM
  • Hi

    Here is a new version which provides for find by either Name, Size.Width, Size.Height or Cost. There is also a BindingNavigator added to ease record navigation.  This version also saves the data on Form Closing and, loads the data if a data file is found (if not found will create the dummy data instead).

    Option Strict On
    Option Explicit On
    ' Form1 with:
    ' Comboboxes (1,2 and 3)
    ' TextBoxes (1,2 and 3)
    ' Button1 and Button2 (if preferred)
    ' BindingNavigator1
    ' some Labels
    Imports System.Runtime.Serialization.Formatters.Binary
    
    Public Class Form1
    	Dim BS As New BindingSource
    	Dim col As New List(Of Equipments)
    	Dim path As String = IO.Path.Combine(Application.StartupPath, "Data", "MyData.dat")
    	Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
    		SaveEquipments()
    	End Sub
    	Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    		If Not IO.Directory.Exists(IO.Directory.GetParent(path).FullName) Then
    			IO.Directory.CreateDirectory(IO.Directory.GetParent(path).FullName)
    		End If
    
    		If IO.File.Exists(path) Then
    			' sata file found so load it
    			ReadEquipments()
    		Else
    			' set up some dummy data
    			For i As Integer = 1 To 99
    				Dim a As New Equipments
    				a.Name = "Name " & i.ToString
    				a.Size = New Size(3 * i, 5 * i)
    				a.Cost = i * 3 / 5
    				col.Add(a)
    			Next
    		End If
    		BS.DataSource = col
    		BindingNavigator1.BindingSource = BS
    		With ComboBox1
    			.DataSource = BS
    			.DisplayMember = "Name"
    		End With
    		With ComboBox2
    			.DataSource = BS
    			.DisplayMember = "Size"
    		End With
    		With ComboBox3
    			.DataSource = BS
    			.DisplayMember = "Cost"
    		End With
    	End Sub
    	Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    		Dim aa As Equipments = TryCast(BS.Current, Equipments)
    		If Not TextBox1.Text = Nothing Then aa.Name = TextBox1.Text
    		If Not TextBox2.Text = Nothing AndAlso Split(TextBox2.Text, ","c).Length = 2 Then aa.Size = New Size(CInt(Split(TextBox2.Text, ","c)(0)), CInt(Split(TextBox2.Text, ","c)(1)))
    		If Not TextBox3.Text = Nothing Then aa.Cost = CDbl(TextBox3.Text)
    		BS.ResetBindings(False)
    	End Sub
    	Private Sub TextBox4_TextChanged(sender As Object, e As EventArgs) Handles TextBox4.TextChanged
    		If TextBox4.Text = Nothing Then Exit Sub
    		BS.Position = col.IndexOf(col.Where(Function(x) x.Name.Contains(TextBox4.Text)).FirstOrDefault)
    		TextBox5.Text = Nothing
    		TextBox6.Text = Nothing
    		TextBox7.Text = Nothing
    	End Sub
    	Private Sub TextBox5_TextChanged(sender As Object, e As EventArgs) Handles TextBox5.TextChanged
    		If TextBox5.Text = Nothing Then Exit Sub
    		BS.Position = col.IndexOf(col.Where(Function(x) x.Size.Width = CInt(TextBox5.Text)).FirstOrDefault)
    		TextBox4.Text = Nothing
    		TextBox6.Text = Nothing
    		TextBox7.Text = Nothing
    	End Sub
    	Private Sub TextBox6_TextChanged(sender As Object, e As EventArgs) Handles TextBox6.TextChanged
    		If TextBox6.Text = Nothing Then Exit Sub
    		BS.Position = col.IndexOf(col.Where(Function(x) x.Size.Height = CInt(TextBox6.Text)).FirstOrDefault)
    		TextBox4.Text = Nothing
    		TextBox5.Text = Nothing
    		TextBox7.Text = Nothing
    	End Sub
    	Private Sub TextBox7_TextChanged(sender As Object, e As EventArgs) Handles TextBox7.TextChanged
    		BS.Position = col.IndexOf(col.Where(Function(x) x.Cost = CDec(TextBox7.Text)).FirstOrDefault)
    		TextBox4.Text = Nothing
    		TextBox5.Text = Nothing
    		TextBox6.Text = Nothing
    	End Sub
    	Public Sub SaveEquipments()
    		Dim fs As IO.FileStream = New IO.FileStream(path, IO.FileMode.OpenOrCreate)
    		Dim bf As New BinaryFormatter()
    		bf.Serialize(fs, col)
    		fs.Close()
    	End Sub
    	Public Sub ReadEquipments()
    		If FileIO.FileSystem.FileExists(path) Then
    			col.Clear()
    			Dim fsRead As New IO.FileStream(path, IO.FileMode.Open)
    			Dim bf As New BinaryFormatter()
    			col = CType(bf.Deserialize(fsRead), List(Of Equipments))
    			fsRead.Close()
    		End If
    	End Sub
    	<Serializable()> Class Equipments
    		Property Name As String
    		Property Size As Size
    		Property Cost As Double
    	End Class
    End Class


    Regards Les, Livingston, Scotland


    • Edited by leshay Saturday, October 3, 2020 5:48 AM
    • Marked as answer by Shan1986 Saturday, October 3, 2020 5:28 PM
    Saturday, October 3, 2020 5:48 AM

All replies

  • Hello,

    What I'm presenting can be found in the following code sample

    I present data via a BindingSource/BindingList (in this case a custom BindingList called SortableBindingList).

    Change a property for the current item and is reflected immediately because the class Customer implements INotifyPropertyChanged.

    CType(CustomersBindingSource.Current, Customer).CompanyName = "XXXXX"
    To change an item that is not current see this code.

    We can also do

    Dim customers = CType(CustomersBindingSource.DataSource, BindingList(Of Customer))
    customers.Item(0).CompanyName = "Changed"
    


    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

    Friday, October 2, 2020 4:40 PM
  • Hi

    Not sure if this will help, but here it is anyway.  This is  stand alone example, and needs the controls in the Designer as listed below.

    The 3 Comboboxes show the current item and the 3 TextBoxes are used to edit the current item accordingly (on button click). NOTE: there is no exception handling included.

    ' Form1 with:
    ' Comboboxes (1,2 and 3)
    ' TextBoxes (1,2 and 3)
    ' Button1
    ' couple of Labels
    Option Strict On
    Option Explicit On
    Public Class Form1
    	Dim BS As New BindingSource
    	Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    		Dim col As New List(Of Equipments)
    		For i As Integer = 0 To 99
    			Dim a As New Equipments
    			a.Name = "Name " & i.ToString
    			a.Size = New Size(3 * i, 5 * i)
    			a.Cost = i * 3 / 5
    			col.Add(a)
    		Next
    		BS.DataSource = col
    		With ComboBox1
    			.DataSource = BS
    			.DisplayMember = "Name"
    		End With
    		With ComboBox2
    			.DataSource = BS
    			.DisplayMember = "Size"
    		End With
    		With ComboBox3
    			.DataSource = BS
    			.DisplayMember = "Cost"
    		End With
    	End Sub
    	Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    		Dim aa As Equipments = TryCast(BS.Current, Equipments)
    		aa.Name = TextBox1.Text
    		aa.Size = New Size(CInt(Split(TextBox2.Text, ","c)(0)), CInt(Split(TextBox2.Text, ","c)(1)))
    		aa.Cost = CDbl(TextBox3.Text)
    		BS.ResetBindings(False)
    	End Sub
    	Class Equipments
    		Property Name As String
    		Property Size As Size
    		Property Cost As Double
    	End Class
    End Class


    Regards Les, Livingston, Scotland

    Friday, October 2, 2020 5:02 PM
  • Thanks Karen and Leshay both works.

    Now how do i programmatically select the row or record by one of it property  value (eg. Name1 or Size1) and make that record as current or selected row?

    thanks

    Friday, October 2, 2020 7:52 PM
  • I removed the BindingList for a ComboBox, does not make sense here.

    See this code. It's in the exact same project as before.

    • Demo's find and position
    • Change current item (can also change other than current item too but not shown)


    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

    • Marked as answer by Shan1986 Saturday, October 3, 2020 5:28 PM
    Friday, October 2, 2020 8:32 PM
  • Hi

    Here is a new version which provides for find by either Name, Size.Width, Size.Height or Cost. There is also a BindingNavigator added to ease record navigation.  This version also saves the data on Form Closing and, loads the data if a data file is found (if not found will create the dummy data instead).

    Option Strict On
    Option Explicit On
    ' Form1 with:
    ' Comboboxes (1,2 and 3)
    ' TextBoxes (1,2 and 3)
    ' Button1 and Button2 (if preferred)
    ' BindingNavigator1
    ' some Labels
    Imports System.Runtime.Serialization.Formatters.Binary
    
    Public Class Form1
    	Dim BS As New BindingSource
    	Dim col As New List(Of Equipments)
    	Dim path As String = IO.Path.Combine(Application.StartupPath, "Data", "MyData.dat")
    	Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
    		SaveEquipments()
    	End Sub
    	Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    		If Not IO.Directory.Exists(IO.Directory.GetParent(path).FullName) Then
    			IO.Directory.CreateDirectory(IO.Directory.GetParent(path).FullName)
    		End If
    
    		If IO.File.Exists(path) Then
    			' sata file found so load it
    			ReadEquipments()
    		Else
    			' set up some dummy data
    			For i As Integer = 1 To 99
    				Dim a As New Equipments
    				a.Name = "Name " & i.ToString
    				a.Size = New Size(3 * i, 5 * i)
    				a.Cost = i * 3 / 5
    				col.Add(a)
    			Next
    		End If
    		BS.DataSource = col
    		BindingNavigator1.BindingSource = BS
    		With ComboBox1
    			.DataSource = BS
    			.DisplayMember = "Name"
    		End With
    		With ComboBox2
    			.DataSource = BS
    			.DisplayMember = "Size"
    		End With
    		With ComboBox3
    			.DataSource = BS
    			.DisplayMember = "Cost"
    		End With
    	End Sub
    	Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    		Dim aa As Equipments = TryCast(BS.Current, Equipments)
    		If Not TextBox1.Text = Nothing Then aa.Name = TextBox1.Text
    		If Not TextBox2.Text = Nothing AndAlso Split(TextBox2.Text, ","c).Length = 2 Then aa.Size = New Size(CInt(Split(TextBox2.Text, ","c)(0)), CInt(Split(TextBox2.Text, ","c)(1)))
    		If Not TextBox3.Text = Nothing Then aa.Cost = CDbl(TextBox3.Text)
    		BS.ResetBindings(False)
    	End Sub
    	Private Sub TextBox4_TextChanged(sender As Object, e As EventArgs) Handles TextBox4.TextChanged
    		If TextBox4.Text = Nothing Then Exit Sub
    		BS.Position = col.IndexOf(col.Where(Function(x) x.Name.Contains(TextBox4.Text)).FirstOrDefault)
    		TextBox5.Text = Nothing
    		TextBox6.Text = Nothing
    		TextBox7.Text = Nothing
    	End Sub
    	Private Sub TextBox5_TextChanged(sender As Object, e As EventArgs) Handles TextBox5.TextChanged
    		If TextBox5.Text = Nothing Then Exit Sub
    		BS.Position = col.IndexOf(col.Where(Function(x) x.Size.Width = CInt(TextBox5.Text)).FirstOrDefault)
    		TextBox4.Text = Nothing
    		TextBox6.Text = Nothing
    		TextBox7.Text = Nothing
    	End Sub
    	Private Sub TextBox6_TextChanged(sender As Object, e As EventArgs) Handles TextBox6.TextChanged
    		If TextBox6.Text = Nothing Then Exit Sub
    		BS.Position = col.IndexOf(col.Where(Function(x) x.Size.Height = CInt(TextBox6.Text)).FirstOrDefault)
    		TextBox4.Text = Nothing
    		TextBox5.Text = Nothing
    		TextBox7.Text = Nothing
    	End Sub
    	Private Sub TextBox7_TextChanged(sender As Object, e As EventArgs) Handles TextBox7.TextChanged
    		BS.Position = col.IndexOf(col.Where(Function(x) x.Cost = CDec(TextBox7.Text)).FirstOrDefault)
    		TextBox4.Text = Nothing
    		TextBox5.Text = Nothing
    		TextBox6.Text = Nothing
    	End Sub
    	Public Sub SaveEquipments()
    		Dim fs As IO.FileStream = New IO.FileStream(path, IO.FileMode.OpenOrCreate)
    		Dim bf As New BinaryFormatter()
    		bf.Serialize(fs, col)
    		fs.Close()
    	End Sub
    	Public Sub ReadEquipments()
    		If FileIO.FileSystem.FileExists(path) Then
    			col.Clear()
    			Dim fsRead As New IO.FileStream(path, IO.FileMode.Open)
    			Dim bf As New BinaryFormatter()
    			col = CType(bf.Deserialize(fsRead), List(Of Equipments))
    			fsRead.Close()
    		End If
    	End Sub
    	<Serializable()> Class Equipments
    		Property Name As String
    		Property Size As Size
    		Property Cost As Double
    	End Class
    End Class


    Regards Les, Livingston, Scotland


    • Edited by leshay Saturday, October 3, 2020 5:48 AM
    • Marked as answer by Shan1986 Saturday, October 3, 2020 5:28 PM
    Saturday, October 3, 2020 5:48 AM
  • Thanks Karen and Leshay for the answers . Both were really very helpful. 
    Saturday, October 3, 2020 5:28 PM
  • Hallo Leshay, How do i serialize to xml instead of dat? thanks
    Saturday, October 3, 2020 6:53 PM
  • Hallo Leshay, How do i serialize to xml instead of dat? thanks

    Hi

    I think you would need to introduce a datatable for the data (which woud then be bound to the BindingSource).  This would enable simple read/write to xml.  I will post an example in a few minutes.


    Regards Les, Livingston, Scotland

    Saturday, October 3, 2020 7:20 PM
  • Hi

    A hurried version (limited testing).  Uses a DataTable instead of a Class, Reads/Writes XM:.  Size search needs both width and height instead of either as previous version.

    Option Strict On
    Option Explicit On
    Public Class Form1
        Dim dt As New DataTable("Equipment")
        Dim BS As New BindingSource
        Dim path As String = IO.Path.Combine(Application.StartupPath, "Data", "MyData.xml")
        Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
            dt.WriteXml(path)
        End Sub
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            If Not IO.Directory.Exists(IO.Directory.GetParent(path).FullName) Then
                IO.Directory.CreateDirectory(IO.Directory.GetParent(path).FullName)
            End If

            With dt
                .Columns.Add("Name", GetType(String))
                .Columns.Add("Size", GetType(String))
                .Columns.Add("Cost", GetType(Decimal))

                If IO.File.Exists(path) Then
                    ' data file found so load it
                    dt.ReadXml(path)
                Else
                    ' set up some dummy data
                    For i As Integer = 1 To 99
                        dt.Rows.Add("Name " & i.ToString, (3 * i).ToString & "," & (5 * i).ToString, (i * 3 / 5).ToString("0.00"))
                    Next
                End If
            End With
            BS.DataSource = dt
            BindingNavigator1.BindingSource = BS
            With ComboBox1
                .DataSource = BS
                .DisplayMember = "Name"
            End With
            With ComboBox2
                .DataSource = BS
                .DisplayMember = "Size"
            End With
            With ComboBox3
                .DataSource = BS
                .DisplayMember = "Cost"
            End With
        End Sub
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Dim aa As DataRowView = DirectCast(BS.Current, DataRowView)
            If Not TextBox1.Text = Nothing Then aa("Name") = TextBox1.Text
            If Not TextBox2.Text = Nothing Then aa("Size") = TextBox2.Text
            If Not TextBox3.Text = Nothing Then aa("Cost") = CDbl(TextBox3.Text)
            BS.ResetBindings(False)
        End Sub
        Private Sub TextBox4_TextChanged(sender As Object, e As EventArgs) Handles TextBox4.TextChanged
            If TextBox4.Text = Nothing Then Exit Sub
            BS.Position = BS.Find("Name", TextBox4.Text)
            TextBox5.Text = Nothing
            TextBox6.Text = Nothing
        End Sub
        Private Sub TextBox5_TextChanged(sender As Object, e As EventArgs) Handles TextBox5.TextChanged
            If TextBox5.Text = Nothing Then Exit Sub
            BS.Position = BS.Find("Size", TextBox5.Text)
            TextBox4.Text = Nothing
            TextBox6.Text = Nothing
        End Sub
        Private Sub TextBox6_TextChanged(sender As Object, e As EventArgs) Handles TextBox6.TextChanged
            If TextBox6.Text = Nothing Then Exit Sub
            BS.Position = BS.Find("Cost", TextBox6.Text)
            TextBox4.Text = Nothing
            TextBox5.Text = Nothing
        End Sub
    End Class


    Regards Les, Livingston, Scotland


    • Edited by leshay Saturday, October 3, 2020 8:09 PM Updated - removed Class code
    Saturday, October 3, 2020 7:58 PM
  • Thanks Leshay.
    Sunday, October 4, 2020 1:32 PM