An Overview
All Eto.Forms.Control
objects have the DataContext
property.
DataContext lets us choose a data object for our View to bind to, this will likely be a ViewModel, or a data object class. But it could even be as simple as an integer (although this would be unusual).
If a View does not have or need bindings, it will likely not need a DataContext object.
The DataContext should not be used for arbitrary data storage, use Tag for this.
The relationship between DataContext and DataStore
Some Controls have a DataStore
property, a good example is the GridView.
The DataStore is similar to the DataContext, but should be used differently.
The DataStore will always be an enumerable, such as a list, array, or better yet, an ObservableCollection<T>
.
Trickle Down
A very useful feature to be aware of is the trickle-down effect of DataContext. Any Control, (including Forms and Dialogs) that has a DataContext will set the DataContext of every child control meaning that this can be accessed anywhere in your UI Tree. If a child control overrides its DataContext with a new DataContext then a new lineage of this DataContext is created.
using Eto.Forms;
using Rhino.UI;
class MyMainViewModel {}
class MyNewViewModel {}
var dialog = new Dialog()
{
DataContext = new MyMainViewModel(), // <-- Start of Main View Model
Content = new TableLayout()
{
Rows = {
new TableRow( // <-- TableRow has a DataContext of MyMainViewModel
new StackLayout() // <-- StackLayout has a DataContext of MyNewViewModel
{
DataContext = new MyNewViewModel(), // <-- Start of New View Model
Items = {
new Drawable(), // <-- Drawable has a DataContext of MyNewViewModel
new Button() // <-- Button has a DataContext of MyNewViewModel
}
}
),
new TableRow( // <-- TableRow has a DataContext of MyMainViewModel
new Button(),
new Button(), // <-- Buttons all have a DataContext of MyMainViewModel
new Button()
),
}
}
};
var parent = RhinoEtoApp.MainWindowForDocument(__rhino_doc__);
dialog.ShowModal(parent);
import scriptcontext as sc
import Rhino
from Rhino.UI import RhinoEtoApp, EtoExtensions
import Eto.Forms as ef
import Eto.Drawing as ed
parent = RhinoEtoApp.MainWindowForDocument(sc.doc)
class MyMainViewModel():
pass
class MyNewViewModel():
pass
stack_layout = ef.StackLayout()
stack_layout.DataContext = ef.MyNewViewModel()
# Drawable has a DataContext of MyNewViewModel
stack_layout.Items.Add(ef.StackLayoutItem(ef.Drawable()))
# Button has a DataContext of MyNewViewModel
stack_layout.Items.Add(ef.StackLayoutItem(ef.Button()))
table_layout = ef.TableLayout()
table_layout.Rows.Add(ef.TableRow(ef.TableCell(stack_layout)))
# Buttons and TableRow all have a DataContext of MyMainViewModel
table_layout.Rows.Add(ef.TableRow(ef.TableCell(ef.Button()), ef.TableCell(ef.Button()), ef.TableCell(ef.Button())))
dialog = ef.Dialog()
dialog.DataContext = ef.MyMainViewModel()
dialog.Content = table_layout
dialog.ShowModal(parent)