Skip to content

Instantly share code, notes, and snippets.

@praeclarum
Created January 3, 2011 15:36
Show Gist options
  • Save praeclarum/763580 to your computer and use it in GitHub Desktop.
Save praeclarum/763580 to your computer and use it in GitHub Desktop.
This class knows how to listen to INotifyCollectionChanged to populate and keep a UITableView in sync with a data source.
using System;
using MonoTouch.UIKit;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using MonoTouch.Foundation;
using System.Collections;
namespace ObservableTableView
{
public class RowSelectedEventArgs : EventArgs {
public object Item { get; set; }
public NSIndexPath Path { get; set; }
}
public delegate void RowSelectedEventHandler(object sender, RowSelectedEventArgs e);
public class ObservableTableViewController : UITableViewController
{
public UITableViewRowAnimation AddAnimation { get; set; }
public UITableViewRowAnimation DeleteAnimation { get; set; }
public UITableViewCellStyle CellStyle { get; set; }
public event RowSelectedEventHandler RowSelected;
Del _del;
Data _data;
IList _collection;
INotifyCollectionChanged _not;
public IList Collection {
get {
return _collection;
}
set {
if (_not != null) {
_not.CollectionChanged -= HandleCollectionChanged;
}
_collection = value;
_not = _collection as INotifyCollectionChanged;
if (_not != null) {
_not.CollectionChanged += HandleCollectionChanged;
TableView.ReloadData();
}
}
}
public ObservableTableViewController (UITableViewStyle withStyle)
: base(withStyle)
{
AddAnimation = UITableViewRowAnimation.Top;
DeleteAnimation = UITableViewRowAnimation.Fade;
CellStyle = UITableViewCellStyle.Default;
_del = new Del(this);
_data = new Data(this);
TableView.Delegate = _del;
TableView.DataSource = _data;
}
protected virtual void DecorateCell(UITableViewCell cell, object item, NSIndexPath path) {
}
protected virtual void OnRowSelected(object item, NSIndexPath path) {
if (RowSelected != null) {
RowSelected(this, new RowSelectedEventArgs() {
Item = item,
Path = path
});
}
}
void HandleCollectionChanged (object sender, NotifyCollectionChangedEventArgs e)
{
TableView.BeginUpdates();
if (e.Action == NotifyCollectionChangedAction.Add) {
var paths = new NSIndexPath[e.NewItems.Count];
for (var i = 0; i < paths.Length; i++) {
paths[i] = NSIndexPath.FromRowSection(e.NewStartingIndex + i, 0);
}
TableView.InsertRows(paths, AddAnimation);
}
else if (e.Action == NotifyCollectionChangedAction.Remove) {
var paths = new NSIndexPath[e.OldItems.Count];
for (var i = 0; i < paths.Length; i++) {
paths[i] = NSIndexPath.FromRowSection(e.OldStartingIndex + i, 0);
}
TableView.DeleteRows(paths, DeleteAnimation);
}
TableView.EndUpdates();
}
class Del : UITableViewDelegate {
ObservableTableViewController _c;
public Del(ObservableTableViewController c) {
_c = c;
}
public override void RowSelected (UITableView tableView, NSIndexPath indexPath)
{
var item = _c.Collection != null ? _c.Collection[indexPath.Row] : null;
_c.OnRowSelected(item, indexPath);
}
}
class Data : UITableViewDataSource {
ObservableTableViewController _c;
NSString _ident;
public Data(ObservableTableViewController c) {
_c = c;
_ident = new NSString("C");
}
public override int NumberOfSections (UITableView tableView)
{
return 1;
}
public override int RowsInSection (UITableView tableview, int section)
{
var coll = _c.Collection;
return coll != null ? coll.Count : 0;
}
public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
{
var cell = tableView.DequeueReusableCell(_ident);
if (cell == null) {
cell = new UITableViewCell(_c.CellStyle, _ident);
}
try {
var coll = _c.Collection;
if (coll != null) {
var obj = coll[indexPath.Row];
_c.DecorateCell(cell, obj, indexPath);
}
return cell;
}
catch {
}
return cell;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment