question

Hobbyistprogrammer-7674 avatar image
0 Votes"
Hobbyistprogrammer-7674 asked Hobbyistprogrammer-7674 answered

Add column to a existing list of Objects ?

Hallo,

I have list of objects bound to datagridview with bindingsource. is there a way to add temporary columns to list and modify values using Linq.

I can add a new column to datagridview using columns.add method but when i use LInq i dont know how to specify this column in linq to modify values.

Thanks

dotnet-visual-basic
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

cooldadtx avatar image
0 Votes"
cooldadtx answered

Knowing nothing else about your system I would say add the properties to your objects. If the values are calculated then make them a calculated property on the object (e.g age of a person given their birth date). If for some reason you cannot modify the actual type itself then consider using a model type instead that wraps the original data and provides a UI-specific view of it to make the UI easier.

Alternatively you could add the column to the DGV directly and then using a binding expression to calculate the value on the fly as well.

If you need to be able to have the user modify the value in the DGV then you have little choice but to add it to the object/model type that you're binding. If you don't then there would be no easy way to get/store the data permanently. While you could rely on the edit events this would be messy in my opinion.

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hobbyistprogrammer-7674 avatar image
0 Votes"
Hobbyistprogrammer-7674 answered

Those columns has to be generated at runtime . I can not add properties before and the whole datagridview is read only and they are not saved. I have to show/bring the values programmatically.

I can add column programmatically to datagridview. I have almost 300 rows in my list and i bring the values using Linq operations to list. In the same loop operation i can bring the values for the added column but i dont know how to cast the values from the linq operation to datagridview added column.

In the worst case i have to make another loop just for the dgv incase if i dont find a better way. here is my sample code .

How can i add lets say i value to the added column in the loop?..


120133-sample.gif


 Public Class Form1
    
     Public BS As New BindingSource
     Public sampleList As New List(Of Item)
    
     Private Sub SampleButton_Click(sender As Object, e As EventArgs) Handles SampleButton.Click
    
         DataGridView1.Columns.Add("Col1", "New Column")
    
         For i = 1 To 3
             Dim c = sampleList.FirstOrDefault(Function(x) x.ID = i)
             c.UnitCost = c.UnitCost * 2
         Next
    
         DataGridView1.Refresh()
    
     End Sub
    
     Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
         sampleList = Mocked.ItemList()
         BS.DataSource = sampleList
         DataGridView1.DataSource = BS
     End Sub
 End Class
    
    
 Public Class Mocked
     Public Shared Function ItemList() As List(Of Item)
         Return New List(Of Item) From {
              New Item() With {.ID = 1, .Item = "A", .UnitCost = 5},
              New Item() With {.ID = 2, .Item = "B", .UnitCost = 10},
              New Item() With {.ID = 3, .Item = "C", .UnitCost = 15}
          }
     End Function
 End Class
    
 Public Class Item
     Public Property ID As Integer
     Public Property Item As String
     Public Property UnitCost As Integer
 End Class



sample.gif (67.2 KiB)
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hobbyistprogrammer-7674 avatar image
0 Votes"
Hobbyistprogrammer-7674 answered cooldadtx commented

Ok. I found a solution

             Dim cRow = DataGridView1.Rows.Cast(Of DataGridViewRow)().FirstOrDefault(Function(r) CBool(r.Cells("ID").Value = i))
             cRow .Cells("Col1").Value = i

In this example it works fine but in my real sample whatever the value i input manually or programmatically ..it disappears immediately . any idea why this is happening?

120104-sample2.gif



sample2.gif (37.9 KiB)
· 2
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

It happens because the DGV expects you to be storing data outside the control. You are binding your grid to some mock data. When you call Refresh it'll reload the DGV with the bound data. Since your new columns don't exist in the dataset it wipes their values. You are going to have to store your new columns' data as well.

It still isn't clear to me what you're trying to accomplish as far as adding dynamic data so it is hard to provide clear direction but the key is going to be ensuring you are storing the data. You can either do that by storing the data external to the DGV (the normal approach and what you're currently doing) or inside the DGV and not use data binding.

If you want to store the data outside the DGV then you'll need a structure that supports dynamically adding new data. A Dataset immediately comes to mind as this is what it is designed for. To add a new column to your DGV you'd insert a new column into the Dataset with some dummy values and then refresh your grid. Of course this assumes you're using auto-generated columns in DGV. If you aren't then you'd need to add the column to the DGV as well.

Alternatively if you already have a type that you cannot expand then add a dictionary that stores new "property" values. Then use data binding to bind the dictionary key to a column. Honestly not sure if this would work though.

0 Votes 0 ·

If this is anything beyond a tutorial or throw away code then you could also create a dynamic object. Dynamic objects allow you to add new fields on the fly and they implement the necessary type to allow DGV to bind to them as normal properties. But this is an advanced scenario to me.

0 Votes 0 ·
Hobbyistprogrammer-7674 avatar image
0 Votes"
Hobbyistprogrammer-7674 answered

I think it is better to use datatable for this purpose as you said. thanks.

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.