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.
- A ViewModel with a
Name
property was stored as the data context of a Dialog - A TextBox’s
Text
property was “bound” to the ViewModel’sName
property in a binding that is stored in the Dialog - When changing the
Text
property of the TextBox, theName
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);
Drop Down
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);