Does ETo support multi-list controls?

Does Eto support input control that allow multiple selections from one list?

I’ve look through here:
https://developer.rhino3d.com/guides/rhinopython/eto-controls-python/
and here:
https://github.com/picoe/Eto/wiki/Controls

and it looks like it only support single selection from list?

I guess I can use loop to add a list of checkbox but it’s little annoying and odd looking, also hard to check multiple.

Any idea? Thank you!

The ListBox does not appear to support a multi-selection. However one possible alternative that isn’t too painful would be to use the Gridivew and hide its header visibility. Since Gridview supports multiple selections it should do what you want.

1 Like

That’s what I planed to do too, thnx!

1 Like

@Jun_Wang I’m also trying to implement multi-list controls. Have you found a way to return the selected items?

I managed to get multiple selections using:

self.m_gridview.AllowMultipleSelection = True

but can’t make sense of

self.m_gridview.SelectedItems

The Documentation isn’t that clear to me.

Also, have you found a way to make the list scrollable, like rs.multilistbox?

I’ve replaced self.m_gridview.SelectedItems with self.m_gridview.SelectedRows. However I still can’t get the selected row indicies from this.

SelectedRows will return an int array of the selected rows.

Accessing the values in each cell of the forms.GridView can be done by using the index position of the value in the .DataStore property. e.g. dialog.m_gridview.DataStore[1][2]

@Trav When I return self.m_gridview.SelectedRows I get back:

<Eto.Wpf.Forms.Controls.GridHandler2+<get_SelectedRows>d__40[[Eto.Forms.GridView, Eto, Version=2.4.6800.27430, Culture=neutral, PublicKeyToken=552281e97c755530],[Eto.Forms.Grid+ICallback, Eto, Version=2.4.6800.27430, Culture=neutral, PublicKeyToken=552281e97c755530]] object at 0x0000000000000081 [Eto.Wpf.Forms.Controls.GridHandler2+<get_SelectedRows>d__40[Eto.Forms.GridView,Eto.Forms.Grid+ICallback]]>

I gather this is an array, but for C#?

I don’t need the values in the cells themselves, just the index of each of the selected rows.

@Alasdair does this example help?

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


class SampleEtoGridviewSelectedRows(forms.Dialog[bool]):

    # Dialog box Class initializer
    def __init__(self):
        # Initialize dialog box
        self.Title = 'Sample Eto: Gridview Get Selected Row Indexes'
        self.Padding = drawing.Padding(10)
        self.Resizable = False

        # Create the Gridview
        self.m_gridview = forms.GridView()
        self.m_gridview.ShowHeader = True
        self.m_gridview.AllowMultipleSelection = True
        self.m_gridview.DataStore = (['first'],['second'],['third'])
        self.m_gridview.SelectedRowsChanged += self.RowsChanged

        # Create Gridview Column
        column1 = forms.GridColumn()
        column1.Editable = False
        column1.Width = 200
        column1.DataCell = forms.TextBoxCell(0)
        self.m_gridview.Columns.Add(column1)

        # Create the default button
        self.DefaultButton = forms.Button(Text = 'OK')
        self.DefaultButton.Click += self.OnOKButtonClick

        # Create a table layout and add all the controls
        layout = forms.DynamicLayout()
        layout.Spacing = drawing.Size(5, 5)
        layout.AddRow(self.m_gridview)
        layout.AddRow(None) # spacer
        layout.AddRow(self.DefaultButton)

        # Set the dialog content
        self.Content = layout

    # Gridview SelectedRows Changed Event
    def RowsChanged (self,sender,e):
        print('Selected Gridview Rows: ' + ' '.join(map(str, self.m_gridview.SelectedRows)))
    # OK button click handler
    def OnOKButtonClick(self, sender, e):
        print('Final Selected Gridview Rows: ' + ' '.join(map(str, self.m_gridview.SelectedRows)))

    ## End of Dialog Class ##

def GridViewSelectedRows():
    dialog = SampleEtoGridviewSelectedRows();
    rc = dialog.ShowModal(Rhino.UI.RhinoEtoApp.MainWindow)

if __name__ == "__main__":
    GridViewSelectedRows()
1 Like

@Trav thankyou! Thats extremely helpful.

Is there a way to make it scrollable, , like rs.multilistbox? When I have a large number of rows the gridview extends off the screen.

I’ve found that there is a Scrollable Class, but I’m having trouble implimenting it. I think it works similarlarly to a Group Box, but when I follow to example for group boxes here I can’t make the example work.

@Alasdair Scollable is a panel that you can place all of your controls in and all of them will scroll together if their height exceeds their parent containers max height. It’s not really what you want in this case.

A simple fix for you is to just define some height value for your gridview. So like self.m_gridview.Height = 200 or whatever you want its max height to be. That will keep it from expanding to fit its collection since the DynamicLayout will let it grow endlessly in height.

1 Like

@Trav yep scrollable combined with self.m_gridview.Height = 200 works well. I had difficulty attaching the scrollable panel to the ETO but I think I figured it out.

    grouplayout = forms.DynamicLayout()
    grouplayout.AddRow(label1)
    grouplayout.AddRow(self.m_gridview)
    self.m_scrollable.Content = grouplayout
    layout.AddRow(self.m_scrollable)

Hello Travis, does this also work in c# (I tried m_gridview.DataStore[1][0] and it gave me an error) ? I need to get the cell value of the selected rows.

thanks,

Bind your gridview to an ObservableCollection of your own data class object then subscribe to row or item selection events in the grid.

There are examples here as well as many other Eto examples GridView example.

1 Like

thanks again, how can we control events in gridView (if we have a textboxCell, or a ComboBoxCell - and we change its value, how can we compare between the old value and the latest one?)

thanks,
Hanan