Tuesday, October 1, 2013

NSTableView binding with MvvmCross

Although Mac support in MvvmCross is in its infancy a lot can be accomplished by following the patterns used for iOS. This post assumes you can get the necessary plumbing working for a basic Xamarin.Mac application using MvvmCross. Most of the setup required for a Mac app can be copied from the iOS code but its beyond the scope of this post.

A NSTableViewSource is what the NSTableView uses to source its data. This is what we want to bind. We want to be able to do the following in our binding code:


This is a standard MvvmCross "Fluent" binding. See Stuarts excellent binding documentation for more information. To achieve this I have created bindable versions of NSTableViewSource, NSTableColumn and NSTableCellView. My code uses a "Cs" prefix instead of NS for the bindable versions. Of course once  (if) this code makes its way back into MvvmCross it will use the standard Mvx naming convention.

One of the big differences between the NSTableView and the UITableView is that the former has a concept of columns. What we want is to be able to specify a binding expression for each column we require. We use the editor in Xcode to do this. In the example below we have setup our NSTableView with a few columns. Notice how the binding expression for the "Process Name" column is specified as a  "User Defined Runtime Attribute" in the inspector.


"Title" is a property in CsTableCellView that simply sets the default NSTextField. Description is a property on my model class that is part of the IEnumerable in my view model.To setup a view as above follow the following steps:

  1. Use a regular NSTableView.
  2. Add the columns you require and change the Custom Class to CsTableColumn as below
  3. Set the bindingText in the "User Defined Runtime Attribute" as mentioned earlier. 
If your model class implements INotifyPropertyChanged any changes to a property will reflect automatically in the column that binds the property.

The code is currently sitting in gists until I get a chance to put it somewhere permanent.