Binding
An introduction to Bindings in Eto
View Models
This section is not for Python, python cannot use View Models and bindings in the same way as C#.

Introduction

Bindings pair properties in view models with UI Elements in the Eto Layout. Let’s look at a very simple example.

using Eto.Forms;
using Eto.Drawing;
using Rhino;
using Rhino.UI;
var parent = RhinoEtoApp.MainWindowForDocument(__rhino_doc__);
public class ViewModel
{
public string Name { get; set; }
}
var nameInput = new TextBox() { Width = 300 };
nameInput.BindDataContext(t => t.Text, (ViewModel vm) => vm.Name);
var viewModel = new ViewModel();
var myDialog = new Dialog()
{
Padding = 12,
Title = "What is your Name?",
DataContext = viewModel,
Content = nameInput
};
myDialog.ShowModal(parent);
RhinoApp.WriteLine(viewModel.Name);

If we use the Script Editor to run this script, a dialog appears with a text box. We can then enter text and hit close. You should see your inputted text printed to the command line.

Let’s examine what happened.

  1. A ViewModel with a Name property was stored as the data context of a Dialog
  2. A TextBox’s Text property was “bound” to the ViewModel’s Name property in a binding that is stored in the Dialog
  3. When changing the Text property of the TextBox, the Name property in the ViewModel is updated with the value

More Binding

Binding goes beyond BindDataContext, even if that might be enough for a simpler UI.

Any binding in Eto can be created with control.Bind<T>, many controls will have binding methods or properties to simplify this. e.g

These create half the binding for you but aren’t strictly necessary.

These 3 snippets are functionally identical but achieve it through helper methods and properties

cb.Bind<bool>(nameof(CheckBox.Checked), DataContext, nameof(ViewModel.Checked));
cb.BindDataContext(c => c.Checked, (ViewModel vm) => vm.Checked);
cb.CheckedBinding.BindDataContext(nameof(ViewModel.Checked));

Lastly there are the BindableExtensions.

All bindings when created on an object are added to the IBindable.Bindings property that all Controls have.

Examples

Why are some of the View Models below more complex than above? This page conveniently side steps that for now, check out this page to learn why.

Check Box

using Eto.Forms;
using Eto.Drawing;
using Rhino.UI;
public class MyViewModel : ViewModel
{
private bool _checked { get; set; }
public bool Checked
{
get => _checked;
set
{
_checked = value;
RaisePropertyChanged(nameof(Checked));
}
}
}
var checkBox = new CheckBox()
{
Text = "Check Please",
Checked = true,
};
checkBox.BindDataContext(c => c.Checked, Binding.Property((MyViewModel vm) => vm.Checked).ToBool(true, false));
// Also works
// checkBox.CheckedBinding.BindDataContext(Binding.Property((MyViewModel vm) => vm.Checked).ToBool(true, false));
var dialog = new Dialog()
{
Padding = 8,
Content = checkBox,
DataContext = new MyViewModel()
};
var parent = RhinoEtoApp.MainWindowForDocument(__rhino_doc__);
dialog.ShowModal(parent);

Text Box

using Eto.Forms;
using Eto.Drawing;
using Rhino.UI;
public class MyViewModel : ViewModel
{
private string _text { get; set; }
public string Text
{
get => _text;
set
{
_text = value;
RaisePropertyChanged(nameof(Text));
}
}
}
var textBox = new TextBox()
{
TextAlignment = TextAlignment.Center,
Width = 200,
PlaceholderText = "example@email.com"
};
textBox.BindDataContext(tb => tb.Text, (MyViewModel vm) => vm.Text);
var dialog = new Dialog()
{
Padding = 8,
Content = textBox
};
var parent = RhinoEtoApp.MainWindowForDocument(__rhino_doc__);
dialog.ShowModal(parent);
using System;
using System.Collections.ObjectModel;
using Eto.Forms;
using Eto.Drawing;
using Rhino.UI;
public class MyViewModel : ViewModel
{
private int _selectedIndex { get; set; }
public int SelectedIndex
{
get => _selectedIndex;
set
{
_selectedIndex = value;
RaisePropertyChanged(nameof(SelectedIndex));
}
}
public ObservableCollection<string> Choices { get; set; } = new () {
"Point", "Curve", "Brep",
};
}
var dropDown = new DropDown();
dropDown.BindDataContext(dd => dd.DataStore, (MyViewModel vm) => vm.Choices);
dropDown.BindDataContext(dd => dd.SelectedIndex, (MyViewModel vm) => vm.SelectedIndex);
var dialog = new Dialog()
{
Padding = 8,
Content = dropDown,
DataContext = new MyViewModel(),
};
var parent = RhinoEtoApp.MainWindowForDocument(__rhino_doc__);
dialog.ShowModal(parent);

More Reading