Xamarin - Documentation

iOS

change platform

  1. Xamarin
  2. iOS
  3. Tutorials
  4. Introduction to MonoTouch.Dialog

Introduction to MonoTouch.Dialog

Building MonoTouch Applications with MonoTouch.Dialog

Note: This document is a work-in-progress. We're publishing it in its pre-release form in order to ensure that Xamarin customers have up-to-date documentation for the MonoTouch 5.2 release.

Brief

The MonoTouch.Dialog (MT.D) toolkit is an indispensable framework for rapid application UI development in MonoTouch. MT.D makes it fast and easy to define complex application UI using a declarative approach, rather than the tedium of navigation controllers, tables, etc. Additionally, MT.D has a flexible set of APIs that provide developers with a complete control or hands off approach, as well as top-shelf features such as pull-to-refresh, background image loading, search support, and dynamic UI generation via JSON data, built in. This guide introduces the different ways to work with MT.D, provides quick start application walkthroughs, and then dives deep into advanced usage.

Sample Code

Elements API Walkthrough

Reflection API Walkthrough

All Elements Demo

Overview

MonoTouch.Dialog, referred to as MT.D for short, is a rapid UI development toolkit that allows developers to build out application screens and navigation using information, rather than the tedium of creating view controllers, tables, etc. As such, it provides a significant simplification of UI development and code reduction. For example, consider the following screenshot:

image 8.png

This entire screen was defined with the following code:

public enum Category
{
    Travel,
    Lodging,
    Books
}
    
public class Expense
{
    [Section("Expense Entry")]

    [Entry("Enter expense name")]
    public string Name;

    [Section("Expense Details")]
 
    [Caption("Description")]
    [Entry]
    public string Details;
    
    [Checkbox]
    public bool IsApproved = true;

    [Caption("Category")]
    public Category ExpenseCategory;
}

When working with tables in iOS, there’s often a ton of repetitious code. For example, every time a table is needed, a data source is needed to populate that table. In an application that has two table-based screens that are connected via a navigation controller, each screen shares a lot of the same code conceptually.

MT.D simplifies that by encapsulating all of that code into a generic API for table creation. It then provides an abstraction on top of that API that allows for a declarative object binding syntax that makes it even easier. As such, there are two APIs available in MT.D:

  • Low-level Elements API – The Elements API is based on creating a hierarchal tree of elements that represent screens and their components. The Elements API gives developers the most flexibility and control in creating UIs. Additionally, the Elements API has advanced support for declarative definition via JSON, which allows for both incredibly fast declaration, as well as dynamic UI generation from a server.
  • High-Level Reflection API – Also known as the Binding API, it’s conceptually similar to an ORM, in which classes are annotated with UI hints and then MT.D automatically creates screens based on the objects and provides a binding between what is displayed (and optionally edited) on screen, and the underlying object backing. The example above illustrated the use of the Reflection API. This API doesn’t provide the fine-grained control that the elements API does, but it reduces complexity even further by automatically building out the element hierarchy based on class decoration.

MT.D comes packed with a large set of built in UI elements for screen creation, but it also recognizes the need for customized elements and advanced screen layouts. As such, extensibility is a first-class featured baked into the API. Developers can extend the existing elements or create new ones and they integrate seamlessly.

Additionally, MT.D has a number of common iOS UX features built in such as “pull-to-refresh” support, background image loading, and search support.
This article will take a comprehensive look at working with MT.D, including:

  • Getting Started – This will focus on getting up to speed using MT.D quickly, including using the Elements API to create the UI hierarchy manually, and then using the Reflection API to define UI declaratively.
  • Elements Reference – This includes a comprehensive list of the built-in elements and components of MT.D.
  • Advanced Usage – This covers advanced features such as pull-to-refresh, search, background image loading, using LINQ to build out element hierarchies, and creating custom elements, cells, and controllers for use with MT.D

Understanding the Pieces of MT.D

Even when using the Reflection API or the JSON API, MT.D creates an Element hierarchy under the hood, just as if it were created via the Elements API directly. For this reason, it’s important to have a basic understanding of the constituent pieces of MT.D.
MT.D builds screens using the following four parts:

  • DialogViewController
  • RootElement
  • Section
  • Element

DialogViewController

A DialogViewController, or DVC for short, inherits from TableViewController and therefore represents a screen with a table. DVCs can be pushed onto a navigation controller just like a regular TableViewController.

RootElement

A RootElement is the top-level container for the items that go into a DVC. It contains Sections, which can then contain Elements. RootElements are not rendered, instead they’re simply containers for what actually gets rendered. A RootElement is assigned to a DVC, and then the DVC renders it’s children.

Section

A section is a group of cells in a table. As with a normal table section, it can optionally have a header and footer that can either be text, or even custom views, as in the following screenshot:

02 - Headers and Footers.png

Element

An Element represents an actual cell in the table. MT.D comes packed with a wide variety of Elements that represent different data types or different inputs. For example, the following screenshots illustrate a few of the available elements:

Smattering of Elements.png

Elements API Walkthrough

 

Now that we have a solid understanding of the different parts of MT.D, let’s put them all together into an application using the Elements API.

In this walkthrough, we’ll create a simple MT.D based master-detail style of application that displays a task list. When the user selects the + button in the upper right, a new row will be added to the table for the task. Selecting the row will navigate to the detail screen to update the task description and the due date as illustrated below:

04 - Task List App.png

Setting up the Multi-Screen Application

MonoTouch.Dialog works by creating a DialogViewController and adding a RootElement to start the screen creation process.

To create a multi-screen application with MonoTouch.Dialog, we need to:

  1. Create a UINavigationController.
  2. Create a DialogViewController.
  3. Add the DialogViewController as the root of the UINavigationController.
  4. Add a RootElement to the DialogViewController.
  5. Add Sections and Elements to the RootElement.

Using UINavigationController

To create a navigation style of application, we need to create a UINavigationController and add it as the RootViewController in the FinishedLaunching method of the AppDelegate. To make the UINavigationController work with MonoTouch.Dialog, we add a DialogViewController to the UINavigationController as shown below:

public override bool FinishedLaunching (UIApplication app,
       NSDictionary options)
{
       _window = new UIWindow (UIScreen.MainScreen.Bounds);
           
       _rootElement = new RootElement ("To Do List"){new Section ()};

       // code to create screens with MT.D will go here …

       _rootVC = new DialogViewController (_rootElement);
       _nav = new UINavigationController (_rootVC);
       _window.RootViewController = _nav;
       _window.MakeKeyAndVisible ();
           
       return true;
}

The code above creates an instance of a RootElement, which it passes into the DialogViewController. The DialogViewControlleralways has a RootElementat the top of its hierarchy. Here the RootElementis created with the string “To Do List” which serves as the title in the navigation controller’s navigation bar. At this point running the application would present the screen shown below:

image 2.png

Let’s see how to add more screens using MonoTouch.Dialog’s hierarchical structure of Sections and Elements.

Creating the Dialog Screens

A DialogViewController is a UITableViewController subclass that MonoTouch.Dialog uses to add screens. MonoTouch.Dialog creates screens by adding a RootElement to a DialogViewController as we saw above. The RootElement can have Section instances to represent the sections of a table. The sections are made up of elements, other sections, or even other RootElements. By nesting RootElements, MonoTouch.Dialog automatically creates a navigation style application, as we’ll see next.

Using DialogViewController

The DialogViewController, being a UITableViewController subclass, has a UITableView as its view. In this example, we want to add items to the table each time the + button is tapped. Since the DialogViewController was added to a UINavigationController, we can use the NavigationItem’s RightBarButton property to add the + button as shown below:

_addButton = new UIBarButtonItem (UIBarButtonSystemItem.Add);
_rootVC.NavigationItem.RightBarButtonItem = _addButton;

When we created the RootElement earlier, we passed it a single Section instance so that we could add elements as the + button is tapped by the user. We can accomplish this in the event handler for the button using the following code:

_addButton.Clicked += (sender, e) => {
               
       ++n;
               
       var task = new Task{Name = "task " + n, DueDate = DateTime.Now};
               
       var taskElement = new RootElement (task.Name){
              new Section () {
                      new EntryElement (task.Name,
                             "Enter task description", task.Description)
              },
              new Section () {
                      new DateElement ("Due Date", task.DueDate)
              }
        };
       _rootElement [0].Add (taskElement);
};

This code creates a new Task object each time the button is tapped. The following shows the simple implementation of the Task class:

public class Task
{  
       public Task ()
       {
       }
       
       public string Name { get; set; }
       
       public string Description { get; set; }

       public DateTime DueDate { get; set; }
}

The task’s Name property is used to create the RootElement’s caption along with a counter variable named n that is incremented for each new task. MonoTouch.Dialog turns this into the rows that are added to the TableView when the taskElement is added.

Presenting and Managing Dialog Screens

We used a RootElement so that MonoTouch.Dialog would automatically create a new screen for each task’s details and navigate to it when a row is selected.

The task detail screen itself is composed of 2 sections each with a single entry. The first entry is created from an EntryElement to provide an editable row for the task’s Description property. When selected, a keyboard is presented to edit the text as shown below:

image 4.png

The second section contains a DateElement to manage the task’s DueDate property. Selecting the date automatically loads a date picker as shown:

image 5.png

In both the EntryElement and DateElement cases (or for any data entry element in MonoTouch.Dialog), the value is preserved automatically after it is changed. We can demonstrate this by editing the date and navigating back and forth between the root screen and various task details, where the values in the detail screens are preserved.

Getting Started with the Reflection API

In addition to the Elements API, MT.D also includes an attribute-based Reflection API. Using the Reflection API is as simple as:

  1. Creating a class decorated with MT.D attributes.
  2. Creating a BindingContext instance, passing it an instance of the above class.
  3. Creating a DialogViewController, passing it the BindingContext’s RootElement.

Let’s look at an example to illustrate how to use the Reflection API. In this example, we’ll build a simple data entry screen as shown below:

image 6.png

Creating a Class with MT.D Attributes

The first thing we need to use the Reflection API is a class decorated with attributes. These attributes will be used by MT.D internally to create objects from the Elements API. For example, consider the following class definition:

public class Expense
{
       [Section("Expense Entry")]

       [Entry("Enter expense name")]
       public string Name;
      
       [Section("Expense Details")]

       [Caption("Description")]
       [Entry]
       public string Details;
      
       [Checkbox]
       public bool IsApproved = true;
}

The SectionAttribute will result in sections of the UITableView being created, with the string argument used to populate the section’s header. Once a section is declared, every field that follows it will be included in that section, until another section is declared. The type of user interface element created for the field will depend upon the field’s type and the MT.D attribute decorating it.

For example, the Name field is a string and it is decorated with an EntryAttribute. This results in a row being added to the table with a text entry field and the specified caption. Similarly, the IsApproved field is a bool with a CheckboxAttribute, resulting in a table row with a checkbox on the right of the table cell. MT.D uses the field name, automatically adding a space, to create the caption in this case, since it is not specified in an attribute.

Adding the BindingContext

To use the Expense class, we need to create a BindingContext. A BindingContext is a class that will bind the data from the attributed class to create the hierarchy of elements. To create one, we simply instantiate it and pass in an instance of the attributed class to the constructor.

For example, to add UI that we declared using attribute in the Expense class, include the following code in the FinishedLaunching method of the AppDelegate:

var expense = new Expense ();
var bctx = new BindingContext (null, expense, "Create a task");

Then all we have to do to create the UI is add the BindingContext to the DialogViewController and set it as the RootViewController of the window, as shown below:

UIWindow window;
public override bool FinishedLaunching (UIApplication app,
       NSDictionary options)
{
       window = new UIWindow (UIScreen.MainScreen.Bounds);
           
       var expense = new Expense ();
       var bctx = new BindingContext (null, expense, "Create a task");
       var dvc = new DialogViewController (bctx.Root);
           
       window.RootViewController = dvc;
       window.MakeKeyAndVisible ();
           
       return true;
}

Running the application now results in the screen shown above being displayed.

Adding a UINavigationController

Notice however that the title “Create a task” that we passed to the BindingContext is not displayed. This is because the DialogViewController is not part of a UINavigatonController. Let’s change the code to add a UINavigationController as the window’s RootViewController, and add the DialogViewController as the root of the UINavigationController as shown below:

nav = new UINavigationController(dvc);
window.RootViewController = nav;

Now when we run the application, the title appears in the UINavigationController’snavigation bar as the screenshot below shows:

image 8.png

By including a UINavigationController, we can now take advantage of other features of MT.D for which navigation is necessary. For example, we can add an enumeration to the Expense class to define the category for the expense, and MT.D will create a selection screen automatically. To demonstrate, modify the Expense class to include an ExpenseCategory field as follows:

public enum Category
{
       Travel,
       Lodging,
       Books
}
      
public class Expense
{
       …

       [Caption("Category")]
       public Category ExpenseCategory;
}

Running the application now results in a new row in the table for the category as shown:

image 8.png

Selecting the row results in the application navigating to a new screen with rows corresponding to the enumeration, as shown below:

image 9.png

More on Sections and RootElements

 

We introduced them in the beginning, and used them in the walkthrough, but let’s discuss them a bit more, as they’re rather customizable

RootElements

At least one RootElement is required to start the MonoTouch.Dialogs process.

If a RootElement is initialized with a section/element value then this value is used to locate a child Element that will provide a summary of the configuration which is rendered on the right-side of the display.

Root elements can also be used inside Sections to trigger loading a new nested configuration page. When used in this mode the caption provided is used while rendered inside a section and is also used as the Title for the subpage. For example:

var root = new RootElement ("Meals") {
    new Section ("Dinner"){
            new RootElement ("Desert", new RadioGroup ("desert", 2) {
                new Section () {
                    new RadioElement ("Ice Cream", "desert"),
                    new RadioElement ("Milkshake", "desert"),
                    new RadioElement ("Chocolate Cake", "desert")
                }
            }
        }
    }
}

In the above example, when the user taps on "Desert", MonoTouch.Dialog will create a new page and navigate to it with the root being "Desert" and having a radio group with three values.

In this particular sample, the radio group will select "Chocolate Cake" in the "Desert" section because we passed the value "2" to the RadioGroup. This means pick the 3rd item on the list (zero-index).

Sections are added by calling the Add method or using the C# 4 initializer syntax. The Insert methods are provided to insert sections with an animation.

If you create the RootElement with a Group instance (instead of a RadioGroup) the summary value of the RootElement when displayed in a Section will be the cummulative count of all the BooleanElements and CheckboxElements that have the same key as the Group.Key value.

Sections

Sections are used to group elements in the screen and they are the only valid direct child of the RootElement. Sections can contain any of the standard elements, including new RootElements.

RootElements embedded in a section are used to navigate to a new deeper level.

Sections can have headers and footers either as strings, or as UIViews. Typically you will just use the strings, but to create custom UIs you can use any UIView as the header or the footer. You can either use a string or a view, you would create them like this:

var section = new Section ("Header", "Footer")

To use views, just pass the views to the constructor:

var header = new UIImageView (Image.FromFile ("sample.png"));
var section = new Section (image)

Built-In Elements

MT.D comes with a number of built-in table cell items known as Elements.

Working with Element Values

Elements that are used to capture user input expose a public "Value" property that holds the current value of the element at any time. It is automatically updated as the user uses the application and does not require any programmer intervention to fetch the state of the control.

This is the behavior for all of the Elements that are part of MonoTouch.Dialog but it is not required for user-created elements.

String Element

Show a caption and a value

StringElement.png

Can use it as a button by providing a delegate

new StringElement (
       "Click me",
       () => { new UIAlertView("Tapped", "String Element Tapped"
, null, "ok", null).Show(); })
Screen Shot 2012-02-07 at 9.05.19 PM.png
Styled String Element

 

Can either create the built-in cell styles, or do custom formatting

Show the various cell types + custom

StyledStringElement.png

This class derives from StringElement but lets developers customize a handful of properties like the Font, the text color, the background cell color, the line breaking mode, the number of lines to display and whether an accessory should be displayed.

Multiline Element

MultilineElement.png

Entry Element

 

Can be regular or password (characters are hidden)

EntryElements.png

 

The EntryElement is used to get user input and is initialized with three values: the caption for the entry that will be shown to the user, a placeholder text (this is the greyed-out text that provides a hint to the user) and the value of the text.

The placeholder and value can be null, the caption can not.

At any point, the value of the EntryElement can be retrieved by accessing its Value property.

Additionally the KeyboardType property can be set at creation time to the keyboard type style desired for the data entry. This can be used to configure the keyboard for numeric input, phone input, url input or email address input (The values of UIKeyboardType).

Boolean Element

BooleanElement.png

Checkbox Element

CheckboxElement.png

Radio Element

 

Need to specify a RadioGroup in the root Element

mtRoot = new RootElement ("Demos", new RadioGroup("MyGroup", 0))

RadioElements.png

 

RootElements are also used to coordinate radio elements. The RadioElement members can span multiple Sections (for example to implement something similar to the ring tone selector and separate custom ring tones from system ringtones). The summary view will show the radio element that is currently selected. To use this, create the Root element with the Group constructor, like this:

var root = new RootElement ("Meals", new RadioGroup ("myGroup", 0))

The name of the group in RadioGroup is used to show the selected value in the containing page (if any) and the value, which is zero in this case, is the index of the first selected item.

Badge Element

BadgeElements.png

Float Element

FloatElement.png

Activity Element

ActivityElement.png

Date Element

DateElement.png

Time Element

TimeElement.png

DateTime Element

DateTimeElement.png

HTML Element

HtmlElement.png

Message Element

MessageElement.png

 

Load More Element

Use this element to allow users to load more items in your list. You can customize the normal and loading captions, as well as the font and text color. The UIActivity indicator starts animating, and the loading caption is displayed when a user taps the cell, and then the NSAction passed into the constructor is executed. Once your code in the NSAction is finished, the UIActivity indicator stops animating and the normal caption is displayed again.

Owner-Drawn Element

This element must be subclassed as it is an abstract class. You should override the Height(RectangleF bounds) method in which you should return the height of the element, as well as Draw(RectangleF bounds, CGContext context, UIView view) in which you should do all your customized drawing within the given bounds, using the context and view parameters. This element does the heavy lifting of subclassing a UIView, and placing it in the Cell to be returned, leaving you only needing to implement two simple overrides. You can see a better sample implementation in the Sample app in the DemoOwnerDrawnElement.cs file.

Here's a very simple example of implementing the class:

public class SampleOwnerDrawnElement : OwnerDrawnElement
{
    public SampleOwnerDrawnElement (string text) : base(UITableViewCellStyle.Default, "sampleOwnerDrawnElement")
    {
        this.Text = text;
    }
    public string Text
    {
        get;set;   
    }
    public override void Draw (RectangleF bounds, CGContext context, UIView view)
    {
        UIColor.White.SetFill();
        context.FillRect(bounds);
        UIColor.Black.SetColor();  
        view.DrawString(this.Text, new RectangleF(10, 15, bounds.Width - 20, bounds.Height - 30), UIFont.BoldSystemFontOfSize(14.0f), UILineBreakMode.TailTruncation);
    }
    public override float Height (RectangleF bounds)
    {
        return 44.0f;
    }
 }
JSON Element

The JsonElement is a sublcass of RootElement that extends a RootElement to be able to load the contents of nested child from a local or remote url.

The JsonElement is a RootElement that can be instantiated in two forms. One version creates a RootElement that will load the contents on demand, these are created by using the JsonElement constructors, which take an extra argument at the end, the url to load the contents from:

var je = new JsonElement ("Dynamic Data", "http://tirania.org/tmp/demo.json");

The other form creates the data from a local file or an existing System.Json.JsonObject that you have already parsed:

var je = JsonElement.FromFile ("json.sample");
using (var reader = File.OpenRead ("json.sample"))
    return JsonElement.FromJson (JsonObject.Load (reader) as JsonObject, arg);

For more information on using JSON with MT.D, see the Using the Elements API with JSON section.

Other Features

Pull-to-Refresh Support

Pull to Refresh is a visual effect originally found in Tweetie2 which became a popular effect among many applications.

To add automatic pull-to-refersh support to your dialogs, you only need to do two things: hook up an event handler to be notified when the user pulls the data and notify the DialogViewController when the data has been loaded to go back to its default state.

Hooking up a notification is simple, just connect to the RefreshRequested event on the DialogViewController, like this:

dvc.RefreshRequested += OnUserRequestedRefresh;

Then on your method OnUserRequestedRefresh, you would queue some data loading, request some data from the net, or spin a thread to compute the data. Once the data has been loaded, you must notify the DialogViewController that the new data is in, and to restore the view to its default state, you do this by calling ReloadComplete:

dvc.ReloadComplete ();

Search Support

To support searching, set the EnableSearch property on your DialogViewController. You can also set the SearchPlaceholder property to use as the watermark text in the search bar.

Searching will change the contents of the view as the user types, it searches the visible fields and shows those to the user. The DialogViewController exposes three methods to programatically initiate, terminate or trigger a new filter operation on the results:

StartSearch, FinishSearch, PerformFilter

The system is extensible, so you can alter this behavior if you want

Background Image Loading

MonoTouch.Dialog incorporates TweetStation's image loader. This image loader can be used to load images in the background, supports caching and can notify your code when the image has been loaded.

It will also limit the number of outgoing network connections.

The image loader is implemented in the ImageLoader class, all you need to do is call the DefaultRequestImage method, you will need to provide the Uri for the image you want to load, as well as an instance of the IImageUpdated interface which will be invoked when the image has been loaded.

The ImageLoader exposes a "Purge()" method that you can call when you want to release all of the images that are currently cached in memory. The current code has a cache for 50 images. If you want to use a different cache size (for instance, if you are expecting the images to be too large that 50 images would be too much), you can just create instances of ImageLoader and pass the number of images you want to keep in the cache.

Using LINQ to Create Element Hierarchy

Via the clever usage of LINQ and C#’s initialization syntax, LINQ can be used to create an element hierarchy, for example, the following code creates a screen from some string arrays:

var rootElement = new RootElement ("LINQ root element") {
    from x in new string [] { "one", "two", "three" }
    select new Section (x) {
       from y in "Hello:World".Split (':')
       select (Element) new StringElement (y)
    }
};

This could easily be combined with an XML data store or data from a database to create complex applications nearly entirely from data.

Extending MT.D

Creating Custom Elements

You can create your own element by deriving from either an existing Element or by deriving from the root class Element.

To create your own Element, you will want to override the following methods:

// To release any heavy resources that you might have
    void Dispose (bool disposing);

    // To retrieve the UITableViewCell for your element
    // you would need to prepare the cell to be reused, in the
    // same way that UITableView expects reusable cells to work
    UITableViewCell GetCell (UITableView tv)

    // To retrieve a "summary" that can be used with
    // a root element to render a summary one level up. 
    string Summary ()
    // To detect when the user has tapped on the cell
    void Selected (DialogViewController dvc, UITableView tableView, NSIndexPath path)
    // If you support search, to probe if the cell matches the user input
    bool Matches (string text)

If your element can have a variable size, you need to implement the IElementSizing interface, which contains one method:

// Returns the height for the cell at indexPath.Section, indexPath.Row
    float GetHeight (UITableView tableView, NSIndexPath indexPath);

If you are planning on implemeneting your GetCell method by calling "base.GetCell(tv)" and customizing the returned cell, you need to also override the CellKey property to return a key that will be unique to your Element, like this:

static NSString MyKey = new NSString ("MyKey");
    protected override NSString CellKey {
        get {
            return MyKey;
        }
    }

This works for most elements, but not for the StringElement and StyledStringElement as those use their own set of keys for various rendering scenarios. You would have to replicate the code in those classes.

DVCs

Both the Reflection and the Elements API use the same DialogViewController. Sometimes you will want to customize the look of the view or you might want to use some features of the UITableViewController that go beyond the basic creation of UIs.

The DialogViewController is merely a subclass of the UITableViewController and you can customize it in the same way that you would customize a UITableViewController.

For example, if you wanted to change the list style to be either Grouped or Plain, you could set this value by changing the property when you create the controller, like this:

var myController = new DialogViewController (root, true){
        Style = UITableViewStyle.Grouped;
    }

For more advanced customizations, like setting the default background for the DialogViewController, you would need to create a subclass of it and override the proper methods.

This example shows how to use an image as the background for the DialogViewController:

class SpiffyDialogViewController : DialogViewController {
    UIImage image;

    public SpiffyDialogViewController (RootElement root, bool pushing, UIImage image)
        : base (root, pushing)
    {
        this.image = image;
    }
    public override LoadView ()
    {
        base.LoadView ();
        var color = UIColor.FromPatternImage(image);
        TableView.BackgroundColor = UIColor.Clear;
        ParentViewController.View.BackgroundColor = color;
    }
}

Another customization point is the following virtual methods in the DialogViewController:

public override Source CreateSizingSource (bool unevenRows)

This method should return a subclass of DialogViewController.Source for cases where your cells are evenly sized, or a subclass of DialogViewController.SizingSource if your cells are uneven.

You can use this override to capture any of the UITableViewSource methods. For example, TweetStation uses this to track when the user has scrolled to the top and update accordingly the number of unread tweets.

Validation

Elements do not provide validation themselves as the models that are well suited for web pages and desktop applications do not map directly to the iPhone interaction model.

If you want to do data validation, you should do this when the user triggers an action with the data entered. For example a "Done" or "Next" buttons on the top toolbar, or some StringElement used as a button to go to the next stage.

This is where you would perform basic input validation, and perhaps more complicated validation like checking for the validity of a user/password combination with a server.

How you notify the user of an error is application specific: you could pop up a UIAlertView or show a hint.