Forked from praeclarum/ObservableTableViewController.cs
Last active
August 29, 2015 14:14
-
-
Save qqilihq/228ed6742f17540344c5 to your computer and use it in GitHub Desktop.
Modifications for Xamarin Unified API, added ability to use from within Xamarin Storyboards.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections; | |
using System.Collections.Specialized; | |
using System.Diagnostics; | |
using Foundation; | |
using UIKit; | |
namespace Praeclarum.UI | |
{ | |
[Register ("ObservableTableViewController")] | |
public class ObservableTableViewController : UITableViewController | |
{ | |
public UITableViewRowAnimation AddAnimation { get; set; } | |
public UITableViewRowAnimation DeleteAnimation { get; set; } | |
object dataSource; | |
IList list; | |
INotifyCollectionChanged notifier; | |
System.Threading.Thread mainThread; | |
bool loadedView = false; | |
public object DataSource { | |
get { | |
return dataSource; | |
} | |
set { | |
if (dataSource == value) | |
return; | |
if (notifier != null) { | |
notifier.CollectionChanged -= HandleCollectionChanged; | |
} | |
dataSource = value; | |
list = value as IList; | |
notifier = value as INotifyCollectionChanged; | |
if (notifier != null) { | |
notifier.CollectionChanged += HandleCollectionChanged; | |
} | |
if (loadedView) { | |
TableView.ReloadData (); | |
} | |
} | |
} | |
public ObservableTableViewController () | |
: base (UITableViewStyle.Plain) | |
{ | |
Initialize (); | |
} | |
public ObservableTableViewController (UITableViewStyle withStyle) | |
: base (withStyle) | |
{ | |
Initialize (); | |
} | |
public ObservableTableViewController (IntPtr handle) | |
: base (handle) | |
{ | |
Initialize(); | |
} | |
void Initialize () | |
{ | |
mainThread = System.Threading.Thread.CurrentThread; | |
AddAnimation = UITableViewRowAnimation.Automatic; | |
DeleteAnimation = UITableViewRowAnimation.Automatic; | |
} | |
public override void ViewDidLoad () | |
{ | |
base.ViewDidLoad (); | |
TableView.Source = CreateSource (); | |
loadedView = true; | |
} | |
protected virtual UITableViewSource CreateSource () | |
{ | |
return new ObservableTableSource (this); | |
} | |
protected virtual UITableViewCell CreateCell (NSString reuseId) | |
{ | |
return new UITableViewCell (UITableViewCellStyle.Default, reuseId); | |
} | |
protected virtual void BindCell (UITableViewCell cell, object item, NSIndexPath indexPath) | |
{ | |
cell.TextLabel.Text = item.ToString (); | |
} | |
protected virtual void OnRowSelected (object item, NSIndexPath indexPath) | |
{ | |
} | |
void HandleCollectionChanged (object sender, NotifyCollectionChangedEventArgs e) | |
{ | |
if (!loadedView) | |
return; | |
Action act = () => { | |
if (e.Action == NotifyCollectionChangedAction.Reset) { | |
TableView.ReloadData (); | |
} | |
if (e.Action == NotifyCollectionChangedAction.Add) { | |
var count = e.NewItems.Count; | |
var paths = new NSIndexPath[count]; | |
for (var i = 0; i < count; i++) { | |
paths [i] = NSIndexPath.FromRowSection (e.NewStartingIndex + i, 0); | |
} | |
TableView.InsertRows (paths, AddAnimation); | |
} else if (e.Action == NotifyCollectionChangedAction.Remove) { | |
var count = e.OldItems.Count; | |
var paths = new NSIndexPath[count]; | |
for (var i = 0; i < count; i++) { | |
paths [i] = NSIndexPath.FromRowSection (e.OldStartingIndex + i, 0); | |
} | |
TableView.DeleteRows (paths, DeleteAnimation); | |
} | |
}; | |
var isMainThread = System.Threading.Thread.CurrentThread == mainThread; | |
if (isMainThread) { | |
act (); | |
} else { | |
NSOperationQueue.MainQueue.AddOperation (act); | |
NSOperationQueue.MainQueue.WaitUntilAllOperationsAreFinished (); | |
} | |
} | |
protected class ObservableTableSource : UITableViewSource | |
{ | |
readonly ObservableTableViewController controller; | |
static readonly NSString reuseId = new NSString ("C"); | |
public ObservableTableSource (ObservableTableViewController controller) | |
{ | |
this.controller = controller; | |
} | |
public override void RowSelected (UITableView tableView, NSIndexPath indexPath) | |
{ | |
var item = controller.list != null ? controller.list [indexPath.Row] : null; | |
try { | |
controller.OnRowSelected (item, indexPath); | |
} catch (Exception ex) { | |
Debug.WriteLine (ex); | |
} | |
} | |
public override nint NumberOfSections (UITableView tableView) | |
{ | |
return 1; | |
} | |
public override nint RowsInSection (UITableView tableview, nint section) | |
{ | |
var coll = controller.list; | |
return coll != null ? coll.Count : 0; | |
} | |
public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath) | |
{ | |
var cell = tableView.DequeueReusableCell (reuseId) ?? | |
controller.CreateCell (reuseId); | |
try { | |
var coll = controller.list; | |
if (coll != null) { | |
var obj = coll[indexPath.Row]; | |
controller.BindCell (cell, obj, indexPath); | |
} | |
return cell; | |
} | |
catch (Exception ex) { | |
Debug.WriteLine (ex); | |
} | |
return cell; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment