A better UITableViewSource in Xamarin iOS

The Xamarin Developer Center has a lot of great content to help developers build apps using Xamarin iOS/Droid using many of the components users expect in modern mobile apps. One very common component is a Table View. In this article I am going to show how to extend the UITableViewSource from the BasicTable sample (update: This is Part0 in the GitHub project I’ve created) to be generic and a bit more flexible. Doing so allows the developer to focus on expanding application functionality and not dealing with boilerplate code over and over. The first step is to make the TableSource class generic, change the internal data structure from a string[] to a List<T> and update the class constructors. Here is what the code looks like after this change:

public class TableSource<T> : UITableViewSource {
  public List<T> Data { get; set; }
  protected string cellIdentifier = "TableCell";

  public TableSource ()
  {
    Data = new List<T> ();
  }

  public TableSource(List<T> data)
  {
    Data = data;
  }

  /// <summary>
  /// Called by the TableView to determine how many cells to create for that particular section.
  /// </summary>
  public override int RowsInSection (UITableView tableview, int section)
  {
    return Data.Count;
  }

We also need to adjust how the GetCell method populates the cell’s title. This is done by changing this the line that sets the cell title from cell.TextLabel.Text = tableItems[indexPath.Row]; to cell.TextLabel.Text = Data[indexPath.Row].ToString();. This convention allows you to easily change what displays in the cell title by overriding the model object’s ToString method.

Now we need to fix the ViewDidLoad method in the HomeScreen class to accommodate these update, which now looks like:

  public override void ViewDidLoad ()
  {
    base.ViewDidLoad ();
    table = new UITableView(View.Bounds); // defaults to Plain style
    table.AutoresizingMask = UIViewAutoresizing.All;
    var tableSource = new TableSource<string>(new List<string>
                                                  {"Vegetables","Fruits","Flower Buds","Legumes","Bulbs","Tubers"});
    table.Source = tableSource;
    Add (table);
  }

Finally, I changed the overridden RowSelected method to use an event. This allows for the customization of row clicks without modifying our base class. For our example app this required two changes. The first to the TableSource class where I replaced the existing RowSelected method:

  /// <summary>
  /// Called when a row is touched
  /// </summary>
  public override void RowSelected (UITableView tableView, NSIndexPath indexPath)
  {
        if (OnRowSelected != null) {
          OnRowSelected (this, new RowSelectedEventArgs (tableView, indexPath));
        }
  }

  public class RowSelectedEventArgs : EventArgs
  {
    public UITableView tableView { get; set; }
    public NSIndexPath indexPath { get; set; }

    public RowSelectedEventArgs(UITableView tableView, NSIndexPath indexPath) : base()
    { 
      this.tableView = tableView;
      this.indexPath = indexPath;
    }
  }

  public event EventHandler<RowSelectedEventArgs> OnRowSelected;

And second where I updated the ViewDidLoad method in the HomeScreen class to handle the row click.

  public override void ViewDidLoad ()
  {
    base.ViewDidLoad ();
    table = new UITableView(View.Bounds); // defaults to Plain style
    table.AutoresizingMask = UIViewAutoresizing.All;
    var tableSource = new TableSource<string>(new List<string>{"Vegetables","Fruits","Flower Buds","Legumes","Bulbs","Tubers"});
    tableSource.OnRowSelected += (object sender, TableSource<string>.RowSelectedEventArgs e) => {
      new UIAlertView("Row Selected", 
        tableSource.Data[e.indexPath.Row].ToString(), null, "OK", null).Show();
      e.tableView.DeselectRow (e.indexPath, true);
    };
    table.Source = tableSource;
    Add (table);
  }

This should give you a good starting point to use UITableView’s in you Xamarin iOS app without having to worry about repeating the UITableViewSource code again and again. The final source is Part1 in my TableDemo GitHub Project.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s