Eto GridView Add New Row?

Hi all,

I am working on a small Eto dialog using GridView and I’m wondering if someone can give me some pointers? In particular, I’m wondering how (if?) I can add a new row to a GridView layout while its being viewed?

I am able to get the grid to show the info I want, but I’d like to be able to add to it (and someday to delete from it…) and wondering if that is possible?

Is that done by modifying the DataStore and refreshing the view somehow? I can add a single ‘blank’ row by adding a list of blank items [ ‘’, ‘’, ‘’, ‘’ ] to the DataStore prior to view, but I’d like to do that dynamically during view?

If anyone has any links, or knows any tutorials for something like that I would much appreciate it!

thanks very much,
@ed.p.may

Hi @ed.p.may,

Just add another item to the collection you are using for your grid’s datastore.

– Dale

Hi @dale - thanks so much for getting back to me. Gotcha - so yes I can definitely do that (add to the DataStore using a click or button during run) but is there something I need to do to ‘refresh’ the window / layout after adding that? Just riffing off the example on the Rhino Developer Docs here I can certainly make a button to add to the DataStore, and it appears to register the change, but it doesn’t seem to change / adjust the Eto dialog itself?

for reference, that code looks like:

import Rhino
import scriptcontext
import System
import Rhino.UI
import Eto.Drawing as drawing
import Eto.Forms as forms

class SampleGridView(forms.Dialog[bool]):

    # Dialog box Class initializer
    def __init__(self):
        self.m_gridview = forms.GridView()
        self.m_gridview.ShowHeader = True
        self.m_gridview.DataStore = [['first pick', 'second pick', 'third pick', True],['second','fourth','last', False]]
        
        column1 = forms.GridColumn()
        column1.HeaderText = 'Column 1'
        column1.Editable = True
        column1.DataCell = forms.TextBoxCell(0)
        self.m_gridview.Columns.Add(column1)
        
        column2 = forms.GridColumn()
        column2.HeaderText = 'Column 2'
        column2.Editable = True
        column2.DataCell = forms.TextBoxCell(1)
        self.m_gridview.Columns.Add(column2)
        
        column3 = forms.GridColumn()
        column3.HeaderText = 'Column 3'
        column3.Editable = True
        column3.DataCell = forms.TextBoxCell(2)
        self.m_gridview.Columns.Add(column3)
        
        column4 = forms.GridColumn()
        column4.HeaderText = 'Column 4'
        column4.Editable = True
        column4.DataCell = forms.CheckBoxCell(3)
        self.m_gridview.Columns.Add(column4)
        
        # Create the default button
        self.AddRow = forms.Button(Text = 'Add Grid Row')
        self.AddRow.Click += self.AddRowButton

        # Create a table layout and add all the controls
        layout = forms.DynamicLayout()
        layout.Padding = drawing.Padding(10)
        layout.Spacing = drawing.Size(5, 5)
        layout.AddRow(None) # spacer
        layout.AddRow(self.AddRow)
        layout.AddRow(self.m_gridview)
        
        self.Content = layout
    
    def AddRowButton(self, sender, e):
        print '::::: The DataStore currently looks like: ', self.m_gridview.DataStore
        print ':::::You just clicked "Add Row", adding ['', '', '', False] to the DataStore'
        self.m_gridview.DataStore.append(['', '', '', False])
        print ':::::Now the DataStore looks like: ', self.m_gridview.DataStore

dialog = SampleGridView();
rc = dialog.ShowModal(Rhino.UI.RhinoEtoApp.MainWindow)

Can you tell where I’m going wrong there? thanks so much for the help!
@ed.p.may

1 Like

Hi @ed.p.may,

Rather than using a simple Python list as your datastore, considering using a collection that implements the INotifyCollectionChanged interface, such as .NET’s ObservableCollection class or Eto’s FilterCollection class. These collections provide notifications when items get added, removed, or when the whole list is refreshed.

– Dale

1 Like

Thanks @dale , I’ll definitely take a look at those options. For now I was able to make my setup work with a dict, but followed the advice in the post here: link

  • move the GridView data to display out to an independant object / location
  • access that data each time the window builds
  • on click/button for add row, modify the data and then rebuild the window using a layout.Clear() and then just build it up again after the data has been changed.

worked so far at least. thanks!
-Ed

BTW, in case is useful to others in the future:

I did go back and revisit this and implemented the FilterCollection in place of a regular list for the DataStore as you recommended. Worked great!

Now when the user changes any values while the window is being viewed, I can just call .DataStore.Refresh() after the changes have been made to the FilterCollection and it all updates in the GridView nicely!

thanks again @dale

@ed.p.may

3 Likes

There is a small error in your original implementation.

Change to following line:

self.m_gridview.DataStore.append(['', '', '', False])

To:

self.m_gridview.DataStore.append( ['', '', '', False], )

The “comma” at the end makes it work correctly.

Hi @dale ,

Could you please re-write this code in a way that it sends a message that the “checkboxcell” is checked or unchecked on click. I have tried "OnCellEdited"for this purpose but it does not work for the checkboxcell.

thanks