Model-View-Controller (MVC) Pattern
Model-View-Controller, or MVC, is a design pattern that is often used in creating mobile applications. In an MVC application, the major building blocks of the application are either model objects, view objects, or controller objects.
Definition of MVC objects
Model objects are used to represent the data in your application. If designed appropriately, model objects can be reused in multiple projects. This is especially important in cross-platform scenarios. For model objects to be reusable, they should not know details about how your views and controllers operate.
View objects represent things on screen. For instance, a button or a table view would be view objects. Primary responsibilities for view objects include drawing themselves on screen and responding to events. View objects should not have direct access to the model.
Controller objects are used to coordinate the models and the views to create the application. Controllers can fetch data from the model and hook it up to the corresponding views in the application. When data needs updated or saved, the controller can help facilitate this task by leveraging the model. Controllers are also responsible for handling application flow, e.g. navigating between screens.
MVC in MonoTouch
Model objects can range in complexity from simple arrays all the way up to complex custom object hierarchies. The data they represent can either be static data contained in the project or dynamic data fetched from a database or the Internet.
View objects in iOS derive from UIView or any of its subclasses, such as UIButton or UISlider. Views can either be standard controls from UIKit or custom view classes derived from UIView.
Controller objects in iOS are represented by subclasses of UIViewController. In an iPhone application, each view controller represents one screen’s worth of data. In an iPad application, a view controller might represent a whole screen or it may just represent a functional unit of the screen such as a controller for a list displayed on the screen. For this tutorial, we will focus on the iPhone scenario since iPad view controller hierarchies can get complicated. Each view controller has a View property that is used to manage its view hierarchy. Methods defined in UIViewController can be overridden in view controller subclasses to participate in what Apple refers to as the View Controller Lifecycle. For instance, a view controller can override LoadView to create and load its view object and override ViewDidLoad to customize the view after it has loaded.
Tutorial: Implementing a basic Model-View-Controller application
In this tutorial, we will create a single screen iPhone application that displays the name and price for a grocery store product. The model object will be a simple C# object called Product with properties for name and price. The view object will be a custom view object called ProductView which will derive from UIView and contain UILabels to display the name and price for a product and a button to raise the price 10 cents. Even though most of the examples you will find on the Internet will use Interface Builder XIBs to create the user interface, the first version of this application will layout the controls in code to show how this is done programmatically. Future tutorials will cover how to create the views in the interface designer in Xcode. The controller will be a subclass of UIViewController which will be called ProductViewController.
Setting up the project
Start by creating an empty iPhone project by selecting File->New->Solution… in MonoTouch and then selecting C#->MonoTouch->iPhone->Empty Project in the New Solution window. Name your project “MVCTutorialOne” as shown in the screenshot and click “OK”.

Right-click on the MVCTutorialOne project node in the Solution pane and select Add->New Folder to create a new folder. Name it “Models”. Then create two more folders named “Views” and “Controllers”. These folders are not required for the application to work, but they help to reinforce which files in the project are supporting which roles in the MVC pattern we are following. When you have finished this step, your project should look like the following screenshot:

Creating the Product model
Right-click on the Models folder and select Add->New File… Select “Empty Class” from the “General” category. Name the class “Product” and click “New”. Add two public properties to the class, a Name property of type string and a Price property of type double. We don’t need the default constructor, so you can delete it if you want. Your model class should look like (or similar) to this:
using System;
namespace MVCTutorialOne
{
public class Product
{
public string Name { get; set; }
public double Price { get; set; }
}
}
Very simple object to represent a basic product.
Creating the Product view
Right-click on the Views folder and select Add->New File… Select “Empty Class” from the “General” category. Name the file “ProductView” and click “New”. There are options in the “MonoTouch” category for creating views with and without view controllers but they all create Interface Builder files for creating the user interface. Since we are creating the view manually in code, we want to start with an empty file.
The following steps are based on the Checklist for Implementing a Custom View which is found in the View Programming Guide for iOS.
Step One: Add using statements for System.Drawing and MonoTouch.UIKit to the top of your ProductView class.
using System.Drawing; using MonoTouch.UIKit;
Step Two: Set the superclass for ProductView to UIView.
public class ProductView : UIView
{
// ...
}
Step Three: According to the checklist, since we are planning to create the view programmatically we need to implement the version of the constructor that takes a frame as the parameter.
// Initialization
public ProductView (RectangleF frame): base(frame)
{
// ...
}
Step Four: The next step in the checklist that pertains to our view is setting the AutoresizingMask, which we’ll add to the constructor. We’ll also set the background color of the view to white.
// Set the background color for the view this.BackgroundColor = UIColor.White; // Set the AutoresizingMask to anchor the view to the top left but // allow height and width to grow this.AutoresizingMask = (UIViewAutoresizing.FlexibleRightMargin | UIViewAutoresizing.FlexibleBottomMargin | UIViewAutoresizing.FlexibleHeight | UIViewAutoresizing.FlexibleWidth);
Step Five: Next up in the custom view checklist is the creation and initialization of the subviews the custom view will manage. In our view we will have 3 subviews: the name label, the price label, and the increment button. Create public properties for the three subviews.
// Subview properties
public UILabel NameLabel { get; set; }
public UILabel PriceLabel { get; set; }
public UIButton IncrementButton { get; set; }
To create the name label and add it to the ProductView, add the following code to the ProductView constructor:
this.NameLabel = new UILabel () {
Frame = new RectangleF (20, 20, 280, 20),
AutoresizingMask = (UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleRightMargin)
};
this.AddSubview (this.NameLabel);
This code sets the location of the name label to be 20px from the top and left of ProductView. It also sets the width to 280px and the height to 20px. All of these are set on the Frame property. The AutoresizingMask is set such that the width will be flexible while remaining anchored to the left side. Add similar code to the constructor to set up the price label (the only difference is the y-coordinate in the Frame):
this.PriceLabel = new UILabel () {
Frame = new RectangleF (20, 49, 280, 20),
AutoresizingMask = (UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleRightMargin)
};
this.AddSubview (this.PriceLabel);
Now we will add code to create the increment button subview.
// Create a default rounded rectangle button
this.IncrementButton = UIButton.FromType (UIButtonType.RoundedRect);
// Set the frame
this.IncrementButton.Frame = new RectangleF (20, 78, 280, 37);
// Adjustible width with left anchor
this.IncrementButton.AutoresizingMask = (UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleRightMargin);
// Set the title to "Increment Price $0.10
this.IncrementButton.SetTitle (String.Format ("Increment Price {0:C}", 0.1), UIControlState.Normal);
this.AddSubview (this.IncrementButton);
Since our subviews don’t require and custom layout and we aren’t handling any touch-based gestures in the ProductView class, we have satisfied the custom view checklist. The final ProductView class should look like this:
using System;
using System.Drawing;
using MonoTouch.UIKit;
namespace MVCTutorialOne
{
public class ProductView : UIView
{
// Subview properties
public UILabel NameLabel { get; set; }
public UILabel PriceLabel { get; set; }
public UIButton IncrementButton { get; set; }
// Initialization
public ProductView (RectangleF frame): base(frame)
{
// Set the background color for the view
this.BackgroundColor = UIColor.White;
// Set the AutoresizingMask to anchor the view to the top left but
this.AutoresizingMask = (UIViewAutoresizing.FlexibleRightMargin | UIViewAutoresizing.FlexibleBottomMargin | UIViewAutoresizing.FlexibleHeight | UIViewAutoresizing.FlexibleWidth);
this.NameLabel = new UILabel () {
Frame = new RectangleF (20, 20, 280, 20),
AutoresizingMask = (UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleRightMargin)
};
this.AddSubview (this.NameLabel);
this.PriceLabel = new UILabel () {
Frame = new RectangleF (20, 49, 280, 20),
AutoresizingMask = (UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleRightMargin)
};
this.AddSubview (this.PriceLabel);
this.IncrementButton = UIButton.FromType (UIButtonType.RoundedRect);
this.IncrementButton.Frame = new RectangleF (20, 78, 280, 37);
this.IncrementButton.AutoresizingMask = (UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleRightMargin);
this.IncrementButton.SetTitle (String.Format ("Increment Price {0:C}", 0.1), UIControlState.Normal);
this.AddSubview (this.IncrementButton);
}
}
}
Creating the Product view controller
Right-click on the Controllers folder and select Add->New File… Select “Empty Class” from the “General” category. Name the file “ProductViewController” and click “New”. There are options in the “MonoTouch” category for creating ViewControllers, but this templated approach will add a lot of methods we won’t need and might make it difficult to understand what is going on. It’s better to build the view controller with only the parts we need.
Step One: Add using statements for System.Drawing and MonoTouch.UIKit to the top of your ProductView class.
using System.Drawing; using MonoTouch.UIKit;
Step Two: Set the superclass for ProductViewController to UIViewController.
public class ProductViewController : UIViewController
{
// ...
}
Step Three: Since our controller will be coordinating a product model and the product view, we will create fields to manage these objects.
// Model private Product _product; // View private ProductView _productView;
Step Four: In the constructor for the view controller, initialize the _product model and set some values for the product. (Note: Since the model object is small and we are using static data, we will create the product here in the constructor for this tutorial. In a situation where we need to fetch more substantial data we’ll need to asynchronously fetch the data at a different point in the process. This will be covered in a later tutorial.)
public ProductViewController ()
{
_product = new Product () { Name = "Strawberry Fizzy Pop", Price = 1.59 };
}
Step Five: We are going to use a few methods that update the _productView’s labels based on the _product model’s values. These will be needed later in the view controller creation process.
public void UpdateNameLabel ()
{
_productView.NameLabel.Text = string.Format ("Product Name: {0}", _product.Name);
}
public void UpdatePriceLabel ()
{
// Format as currency
_productView.PriceLabel.Text = string.Format ("Price: {0:C}", _product.Price);
}
Step Six: Next, we need to override the LoadView method. This method is used to programmatically load the view for the view controller when an Interface Builder XIB is not being used to create the view. We didn’t create or refer to the view in the view controller’s constructor because iOS lazy loads the view controller’s view. LoadView will only be called if the ProductViewController.View property is accessed and is null at the time of access.
public override void LoadView ()
{
// Set the frame for the product view to fill the screen taking into
// account the 20px tall status bar.
_productView = new ProductView (new RectangleF (0, 20, 320, 460));
this.View = _productView;
}
Step Seven: Once the view has loaded, there is a method that will get called on the view controller called ViewDidLoad. We can override this method to provide code to customize the newly loaded view. All of the view hierarchy for the view controller will have been created by this point so it is safe to update these objects. We first call base.ViewDidLoad() to allow for superclass initialization. Then, we call the UpdateNameLabel() and UpdatePriceLabel() methods to set their text based on the _product model.
if (_product != null) {
UpdateNameLabel ();
UpdatePriceLabel ();
}
In the MVC object introduction I mentioned that one of the view responsibilities was responding to events. ProductView’s IncrementButton object can respond to a variety of touch related events. The one we are interested in is the TouchUpInside event which will fire when a user presses and releases the button. We will set up an event handler for this event in the ViewDidLoad method the first updates the _product model’s Price property and then calls UpdatePriceLabel() to refresh the price label based on the new model value. (Note: I am using lambda syntax but you can use a delegate as you would with any other event.) This is a very good example of the type of coordination work a controller performs in the MVC pattern.
_productView.IncrementButton.TouchUpInside += (s,e) => {
_product.Price += 0.1;
UpdatePriceLabel ();
};
Step Eight: There is one last method we will override in our view controller for this tutorial. This method is the ShouldAutorotateToInterfaceOrientation (UIInterfaceOrientation toInterfaceOrientation) method. By overriding this method we can define which orientations we wish to support in the application. For this tutorial, we will support all orientations except PortraitUpsideDown.
public override bool ShouldAutorotateToInterfaceOrientation (UIInterfaceOrientation toInterfaceOrientation)
{
// Support all but the "upside down iPhone" orientations
return toInterfaceOrientation != UIInterfaceOrientation.PortraitUpsideDown;
}
At this point, the view controller code is complete. All iOS applications have a single window which can contain a view hierarchy. To add our ProductViewController’s view to the window, we’ll need tocreate an instance of ProductViewController in the AppDelegate’s FinishedLaunching method and add its view to the application window’s subviews.
var pvc = new ProductViewController (); window.AddSubview (pvc.View);
Once this step is completed, our app is done. Run the application and try pressing the Increment button to see the price change.
Get the code
If you’re having trouble with recreating the tutorial, you can find the original source on GitHub at https://github.com/brentschooley/monotouch-tutorials
Conclusion
This article and corresponding tutorial introduced the Model-View-Controller pattern that is used in MonoTouch. We created a simple model object, a custom view to represent it, and a controller object to make them work together within the iOS framework. The next tutorial will cover creating the view objects as Interface Builder XIB files and hooking them up to a view controller. A follow-up to that tutorial will cover how to load a data model from a SQLite database asynchronously and display it in a table view.

