ETO GridView rhino 8 and python 3

Hi all,

Trying to create a simple ETO modeless dialog in Rhino 8 and Python 3 with a GridView.

I cannot seem to get the DataStore contents to render in the table. The data does exist, and adding a ClickEvent shows that data is stored in the element.

Minimal code example below, with the ClickEvent which prints cell content clicked to the Rhino commandline.

Any ideas to what I am doing wrong?

I did have to change the DataStore from a list of lists to a list of tuples to make it work from IronPython → Python3.

Works in p3:

GridTable.DataStore = [("UUID 1", "1"), ("UUID 2", "2")]

Doesn’t work in p3:

GridTable.DataStore = [["UUID 1", "1"], ["UUID 2", "2"]]
#! python3

################################################################################
# SampleEtoDialog.py
# MIT License - Copyright (c) 2017 Robert McNeel & Associates.
# See License.md in the root of this repository for details.
################################################################################
import Rhino.UI
import Eto.Drawing as drawing
import Eto.Forms as forms
import rhinoscriptsyntax as rs
import Rhino


################################################################################
# Sample dialog
################################################################################

class ModelessDlg(forms.Form):
    def __init__(self):
        super().__init__()

        self.Title = "Sample Eto Dialog"
        self.ClientSize = drawing.Size(200, 200)
        self.Padding = drawing.Padding(5)
        self.Resizable = True

        # Create gridviewtable
        self.mygridtable = CreateGridTable()
        
        # Create the layout of the form
        layout = forms.DynamicLayout()
        layout.Spacing = drawing.Size(5, 5)
        layout.AddRow(self.mygridtable)

        # Adds the tabular layout to the main form
        self.Content = layout


# Creates and return table function
def CreateGridTable():

    #Create Gridview
    GridTable = forms.GridView()
    GridTable.Height = 600
    GridTable.Width = 600
    GridTable.ShowHeader = True
    GridTable.DataStore = [("UUID 1", "1"), ("UUID 2", "2")]
    GridTable.CellClick += OnCellClick

    # Add columns
    c = 0
    column = forms.GridColumn()
    column.HeaderText = 'UUID'
    column.DataCell = forms.TextBoxCell(c)
    GridTable.Columns.Add(column)

    c += 1
    column = forms.GridColumn()
    column.HeaderText = 'Type'
    column.DataCell = forms.TextBoxCell(c)
    GridTable.Columns.Add(column)

    return GridTable


def OnCellClick(sender, e):
    if e.Item:
        rprint(e.Item[e.Column])


def showdlg():
    dlg = ModelessDlg()
    dlg.Owner = Rhino.UI.RhinoEtoApp.MainWindow
    dlg.Location = drawing.Point(5, 5)
    dlg.Show()
    return dlg


def rprint(msg):
    if isinstance(msg, str):
        Rhino.RhinoApp.WriteLine(msg)
    else:
        Rhino.RhinoApp.WriteLine(str(msg))
    

################################################################################
# Check to see if this file is being executed as the "main" python
# script instead of being used as a module by some other python script
# This allows us to use the module which ever way we want.
################################################################################
if __name__ == "__main__":
    dlg = showdlg()

@etiennekasteel Python 3 interops very differently with dotnet, in this case the dotnet Eto library. Currently the automatic casting to TreeGridItem does not happen correctly. I created a ticket so I can look into this: RH-82477 Python 3 implicit cast issue

For now create the tree items directly:

GridTable.DataStore = [
        forms.TreeGridItem(["UUID 1", "1"]),
        forms.TreeGridItem(["UUID 2", "2"])
    ]

And to grab value from column, use the .Values property of the tree items:

def OnCellClick(sender, e):
    if e.Item:
        rprint(e.Item.Values[e.Column])

Works like a charm! Thank you.

1 Like