For iOS, you can take advantage of the native UITableView
control's reordering functionality. Create a custom renderer for a ListView
that tells iOS that you'd like all rows to be movable. Have it update the source list's order to match the user's actions.
Start with a subclass.
public class EditListView : ListView { }
Then add a custom renderer that updates ListView.ItemsSource
to reflect the changed order. This code assumes ItemsSource
is a List<ListItem>
, where ListItem
has Id
and Name
properties of type string.
[assembly: ExportRenderer(typeof(EditListView), typeof(EditListViewRenderer))]
public class EditListViewRenderer : ListViewRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<ListView> e)
{
base.OnElementChanged(e);
if (e.NewElement != null) {
Control.Source = new TableViewSource((List<ListItem>)e.NewElement.ItemsSource);
Control.Editing = true;
}
}
class TableViewSource : UITableViewSource
{
readonly List<ListItem> items;
public TableViewSource(List<ListItem> items) { this.items = items; }
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
var item = items[indexPath.Row];
var cell = new UITableViewCell(UITableViewCellStyle.Default, item.Id); // No recycling. If the list is big enough to need recycling, the user won't be very happy about reordering it by hand. :-)
cell.TextLabel.Text = item.Name;
return cell;
}
public override void MoveRow(UITableView tableView, NSIndexPath sourceIndexPath, NSIndexPath destinationIndexPath)
{
int source = sourceIndexPath.Row, dest = destinationIndexPath.Row;
var movedItem = items[source];
items.RemoveAt(source);
if (source > dest) --source;
items.Insert(dest, movedItem);
}
public override nint RowsInSection(UITableView tableview, nint section) => items.Count;
public override bool CanMoveRow(UITableView tableView, NSIndexPath indexPath) => true;
public override bool CanEditRow(UITableView tableView, NSIndexPath indexPath) => true; // Only editable rows can be moved.
public override bool ShouldIndentWhileEditing(UITableView tableView, NSIndexPath indexPath) => false;
public override UITableViewCellEditingStyle EditingStyleForRow(UITableView tableView, NSIndexPath indexPath) => UITableViewCellEditingStyle.None;
}
}