DataSource: Binding with UI Controls

TKDataSource works well with data enabled controls and provides an easy way to shape and present your data. The currently supported UI controls are:

  • UITableView
  • UICollectionView
  • TKListView
  • TKChart
  • TKCalendar

This article describes how to bind TKDataSource and customize those controls.

UITableView

Setting the dataSource property is enough in order to present data in UITableView. TKDataSource will take care of the implementation of all methods in UITableViewDataSource protocol:

NSObject[] array = new NSObject[] {
    NSObject.FromObject (10),
    NSObject.FromObject (5),
    NSObject.FromObject (12),
    NSObject.FromObject (13),
    NSObject.FromObject (7),
    NSObject.FromObject (44)
};

this.dataSource = new TKDataSource (array);

CGRect rect = this.View.Bounds;
rect.Inflate (0, -30);
UITableView table = new UITableView (rect);
table.AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight;
table.DataSource = this.dataSource;
this.View.AddSubview (table);

You can specify displayKey and valueKey properties to specify what to display in table view cells:

NSMutableArray items = new NSMutableArray();
items.Add (new DSItem () { Name = "John", Value = 50, Group = "A" });
items.Add (new DSItem () { Name = "Abby", Value = 33, Group = "A" });
items.Add (new DSItem () { Name = "Smith", Value = 42, Group = "B" });
items.Add (new DSItem () { Name = "Peter", Value = 28, Group = "B" });
items.Add (new DSItem () { Name = "Paula", Value = 25, Group = "B" });

this.dataSource = new TKDataSource ();
this.dataSource.ItemSource = items;
this.dataSource.DisplayKey = "Name";

In the majority of the scenarios you will also need to customize the cells. In this case you can implement the initCell block from TKDataSourceTableViewSettings class:

this.dataSource.Settings.TableView.InitCell ((UITableView tableView, NSIndexPath indexPath, UITableViewCell cell, NSObject item) => {
    cell.TextLabel.Text = "Item:";
    cell.DetailTextLabel.Text = this.dataSource.TextFromItem(item, null);
});

If this is not enough to achieve to look you want, you can create your custom cells by using the createCell block function:

this.dataSource.Settings.TableView.CreateCell ((UITableView tableView, NSIndexPath indexPath, NSObject item) => {
    UITableViewCell cell = tableView.DequeueReusableCell("cell");
    if (cell == null) {
        cell = new UITableViewCell(UITableViewCellStyle.Value1, "cell");
    }
    return cell;
});

TKDataSource will take care of everything and no code is necessary even when your data is grouped:

this.dataSource.Group ((NSObject item) => {
    return NSObject.FromObject(((NSNumber)item).Int32Value % 2 == 0);
});

UICollectionView

TKDataSource integrates well with UICollectionView. Just set the dataSource property and prepare the collection view:

var layout = new UICollectionViewFlowLayout();
layout.ItemSize = new CGSize (140, 140);

CGRect rect = this.View.Bounds;
rect.Inflate (0, -30);
var collectionView = new UICollectionView (rect, layout);
collectionView.AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight;
collectionView.DataSource = this.dataSource;
collectionView.BackgroundColor = UIColor.White;
this.View.AddSubview(collectionView);

Use the collection view settings class and its initCell in case you want to customize the cell appearance:

this.dataSource.Settings.CollectionView.InitCell ((UICollectionView collection, NSIndexPath indexPath, UICollectionViewCell cell, NSObject item) => {
    var tkCell = cell as TKCollectionViewCell;
    tkCell.Label.Text = this.dataSource.TextFromItem(item, null);
    tkCell.BackgroundColor = UIColor.Yellow;
});

TKListView

You can also easily use TKListView with TKDataSource:

CGRect rect = this.View.Bounds;
rect.Inflate (0, -30);
var listView = new TKListView (rect);
listView.AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight;
this.dataSource.SetDataSourceFor (listView);
this.View.AddSubview (listView);

The initCell and createCell methods can be used to customize the cell appearance:

this.dataSource.Settings.ListView.CreateCell ((TKListView list1, NSIndexPath indexPath, NSObject item) => {
    return list1.DequeueReusableCell("myCustomCell", indexPath) as TKListViewCell;
});

this.dataSource.Settings.ListView.InitCell ((TKListView list2, NSIndexPath indexPath, TKListViewCell cell, NSObject item) => {
    cell.TextLabel.Text = this.dataSource.TextFromItem(item, null);
    (cell.BackgroundView as TKView).Fill = new TKSolidFill(new UIColor(0.1f, 0.1f, 0.1f, 0.1f));
});

TKChart

In order to present data in TKChart, you need to set the displayKey and valueKey properties. The displayKey defines the x-axis values, and the valueKey defines the y-axis values:

NSMutableArray items = new NSMutableArray ();
items.Add (new DSItem () { Name = "John", Value = 50, Group = "A" });
items.Add (new DSItem () { Name = "Abby", Value = 33, Group = "A" });
items.Add (new DSItem () { Name = "Paula", Value = 33, Group = "A" });

items.Add (new DSItem () { Name = "John", Value = 42, Group = "B" });
items.Add (new DSItem () { Name = "Abby", Value = 28, Group = "B" });
items.Add (new DSItem () { Name = "Paula", Value = 25, Group = "B" });

this.dataSource.DisplayKey = "Name";
this.dataSource.ValueKey = "Value";
this.dataSource.ItemSource = items;

var chart = new TKChart(this.View.Bounds);
chart.AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight;
chart.DataSource = this.dataSource;
this.View.AddSubview(chart);

In order to present different series the data should be grouped. When this is done the createSeries method can be used to customize the series that should be created:

this.dataSource.GroupWithKey ("Group");

this.dataSource.Settings.Chart.CreateSeries ((TKDataSourceGroup group) => {
    var series = new TKChartColumnSeries();
    return series;
});

TKCalendar

TKDataSource is able to represent your data as calendar events. In this scenario you should set the startDateKey and endDateKey properties:

this.dataSource.DisplayKey = "Name";
this.dataSource.Settings.Calendar.StartDateKey = "StartDate";
this.dataSource.Settings.Calendar.EndDateKey = "EndDate";
this.dataSource.Settings.Calendar.DefaultEventColor = UIColor.Red;
this.dataSource.ItemSource = items;

var calendar = new TKCalendar (this.View.Bounds);
calendar.AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight;
this.dataSource.SetDataSourceFor (calendar);
this.View.AddSubview (calendar);