Freigeben über


Bearbeiten von Tabellen mit Xamarin.iOS

Tabellenbearbeitungsfeatures werden durch Überschreiben von Methoden in einer UITableViewSource Unterklasse aktiviert. Das einfachste Bearbeitungsverhalten ist die Wisch-zu-Löschgeste, die mit einer einzigen Methodenüberschreibung implementiert werden kann. Komplexere Bearbeitung (einschließlich verschiebender Zeilen) können mit der Tabelle im Bearbeitungsmodus erfolgen.

Zum Löschen wischen

Das Feature zum Löschen wischen ist eine natürliche Geste in iOS, die Benutzer erwarten.

Beispiel für Wischen zum Löschen

Es gibt drei Methodenüberschreibungen, die sich auf die Streifbewegung auswirken, um eine Schaltfläche "Löschen " in einer Zelle anzuzeigen:

  • CommitEditingStyle – Die Tabellenquelle erkennt, ob diese Methode überschrieben wird und die Streifbewegung zum Löschen automatisch aktiviert. Die Implementierung der Methode sollte aufrufen DeleteRowsUITableView , um zu bewirken, dass die Zellen ausgeblendet werden, und auch die zugrunde liegenden Daten aus Ihrem Modell entfernen (z. B. ein Array, ein Wörterbuch oder eine Datenbank).
  • CanEditRow – Wenn CommitEditingStyle überschrieben wird, werden alle Zeilen als bearbeitbar angenommen. Wenn diese Methode implementiert ist und "false" (für bestimmte Zeilen oder für alle Zeilen) zurückgibt, ist die Streifbewegung zum Löschen in dieser Zelle nicht verfügbar.
  • TitleForDeleteConfirmation – Gibt optional den Text für die Schaltfläche "Löschen " an. Wenn diese Methode nicht implementiert ist, lautet der Schaltflächentext "Delete".

Diese Methoden werden in der TableSource Klasse wie folgt implementiert:

public override void CommitEditingStyle (UITableView tableView, UITableViewCellEditingStyle editingStyle, Foundation.NSIndexPath indexPath)
{
    switch (editingStyle) {
        case UITableViewCellEditingStyle.Delete:
            // remove the item from the underlying data source
            tableItems.RemoveAt(indexPath.Row);
            // delete the row from the table
            tableView.DeleteRows (new NSIndexPath[] { indexPath }, UITableViewRowAnimation.Fade);
            break;
        case UITableViewCellEditingStyle.None:
            Console.WriteLine ("CommitEditingStyle:None called");
            break;
    }
}
public override bool CanEditRow (UITableView tableView, NSIndexPath indexPath)
{
    return true; // return false if you wish to disable editing for a specific indexPath or for all rows
}
public override string TitleForDeleteConfirmation (UITableView tableView, NSIndexPath indexPath)
{   // Optional - default text is 'Delete'
    return "Trash (" + tableItems[indexPath.Row].SubHeading + ")";
}

In diesem Beispiel wurde die UITableViewSource Aktualisierung so aktualisiert, dass ein List<TableItem> (anstelle eines Zeichenfolgenarrays) als Datenquelle verwendet wird, da es das Hinzufügen und Löschen von Elementen aus der Auflistung unterstützt.

Bearbeitungsmodus

Wenn sich eine Tabelle im Bearbeitungsmodus befindet, sieht der Benutzer ein rotes "Stopp"-Widget in jeder Zeile, das eine Schaltfläche "Löschen" anzeigt, wenn sie berührt wird. In der Tabelle wird auch ein "Handle"-Symbol angezeigt, um anzugeben, dass die Zeile gezogen werden kann, um die Reihenfolge zu ändern. Im TableEditMode-Beispiel werden diese Features wie dargestellt implementiert.

Das TableEditMode-Beispiel implementiert diese Features wie dargestellt.

Es gibt eine Reihe verschiedener Methoden, die UITableViewSource sich auf das Bearbeitungsmodusverhalten einer Tabelle auswirken:

  • CanEditRow – gibt an, ob jede Zeile bearbeitet werden kann. Gibt "false" zurück, um zu verhindern, dass sowohl Wisch-zu-Löschen als auch Löschvorgänge im Bearbeitungsmodus ausgeführt werden.
  • CanMoveRow – Gibt "true" zurück, um die Verschiebung "Handle" oder "false" zu aktivieren, um das Verschieben zu verhindern.
  • EditingStyleForRow – Wenn sich die Tabelle im Bearbeitungsmodus befindet, bestimmt der Rückgabewert dieser Methode, ob in der Zelle das rote Löschsymbol oder das grüne Add-Symbol angezeigt wird. Gibt zurück UITableViewCellEditingStyle.None , wenn die Zeile nicht bearbeitet werden kann.
  • MoveRow – wird aufgerufen, wenn eine Zeile verschoben wird, sodass die zugrunde liegende Datenstruktur so geändert werden kann, dass sie mit den Daten übereinstimmt, wie sie in der Tabelle angezeigt wird.

Die Implementierung der ersten drei Methoden ist relativ direkt vorwärts – es sei denn, Sie möchten das indexPath Verhalten bestimmter Zeilen ändern, hartcodieren Sie nur die Rückgabewerte für die gesamte Tabelle.

public override bool CanEditRow (UITableView tableView, NSIndexPath indexPath)
{
    return true; // return false if you wish to disable editing for a specific indexPath or for all rows
}
public override bool CanMoveRow (UITableView tableView, NSIndexPath indexPath)
{
    return true; // return false if you don't allow re-ordering
}
public override UITableViewCellEditingStyle EditingStyleForRow (UITableView tableView, NSIndexPath indexPath)
{
    return UITableViewCellEditingStyle.Delete; // this example doesn't support Insert
}

Die MoveRow Implementierung ist etwas komplizierter, da sie die zugrunde liegende Datenstruktur so ändern muss, dass sie der neuen Reihenfolge entspricht. Da die Daten als List code unten implementiert werden, löscht das Datenelement an seinem alten Speicherort und fügt es an der neuen Position ein. Wenn die Daten in einer SQLite-Datenbanktabelle mit einer "order"-Spalte (z. B. ) gespeichert wurden, müsste diese Methode stattdessen einige SQL-Vorgänge ausführen, um die Zahlen in dieser Spalte neu anzuordnen.

public override void MoveRow (UITableView tableView, NSIndexPath sourceIndexPath, NSIndexPath destinationIndexPath)
{
    var item = tableItems[sourceIndexPath.Row];
    var deleteAt = sourceIndexPath.Row;
    var insertAt = destinationIndexPath.Row;

    // are we inserting
    if (destinationIndexPath.Row < sourceIndexPath.Row) {
        // add one to where we delete, because we're increasing the index by inserting
        deleteAt += 1;
    } else {
        // add one to where we insert, because we haven't deleted the original yet
        insertAt += 1;
    }
    tableItems.Insert (insertAt, item);
    tableItems.RemoveAt (deleteAt);
}

Um die Tabelle in den Bearbeitungsmodus zu bringen, muss die Schaltfläche "Bearbeiten " wie folgt aufgerufen SetEditing werden.

table.SetEditing (true, true);

und wenn der Benutzer die Bearbeitung abgeschlossen hat, sollte die Schaltfläche "Fertig" den Bearbeitungsmodus deaktivieren:

table.SetEditing (false, true);

Bearbeitungsformat für Zeileneinfügung

Die Zeileneinfügung innerhalb der Tabelle ist eine ungewöhnliche Benutzeroberfläche – das Standard Beispiel in den iOS-Standard-Apps ist der Bildschirm "Kontakt bearbeiten". Dieser Screenshot zeigt, wie die Zeileneinfügefunktion funktioniert – im Bearbeitungsmodus gibt es eine zusätzliche Zeile, die (wenn darauf geklickt wird) zusätzliche Zeilen in die Daten einfügt. Wenn die Bearbeitung abgeschlossen ist, wird die temporäre Zeile (neue Hinzufügen) entfernt.

Wenn die Bearbeitung abgeschlossen ist, wird die temporäre Zeile zum Hinzufügen einer neuen Zeile entfernt.

Es gibt eine Reihe verschiedener Methoden, die UITableViewSource sich auf das Bearbeitungsmodusverhalten einer Tabelle auswirken. Diese Methoden wurden wie folgt im Beispielcode implementiert:

  • EditingStyleForRow – Gibt UITableViewCellEditingStyle.Delete für die Zeilen zurück, die Daten enthalten, und gibt UITableViewCellEditingStyle.Insert sie für die letzte Zeile zurück (die speziell zum Verhalten als Einfügeschaltfläche hinzugefügt wird).
  • CustomizeMoveTarget – Während der Benutzer eine Zelle bewegt, kann der Rückgabewert dieser optionalen Methode die Auswahl der Position überschreiben. Dies bedeutet, dass Sie verhindern können, dass sie die Zelle an bestimmten Positionen "ablegen", z. B. in diesem Beispiel, das verhindert, dass alle Zeilen nach der Zeile verschoben werden (neue Hinzufügen).
  • CanMoveRow – Gibt "true" zurück, um die Verschiebung "Handle" oder "false" zu aktivieren, um das Verschieben zu verhindern. Im Beispiel hat die letzte Zeile das Verschieben des Handles ausgeblendet, da sie nur als Einfügeschaltfläche serveriert werden soll.

Außerdem fügen wir zwei benutzerdefinierte Methoden hinzu, um die Zeile "einfügen" hinzuzufügen, und entfernen sie dann erneut, wenn sie nicht mehr benötigt wird. Sie werden über die Schaltflächen "Bearbeiten" und "Fertig " aufgerufen:

  • WillBeginTableEditing – Wenn die Schaltfläche "Bearbeiten " berührt wird, wird sie aufgerufen SetEditing , um die Tabelle im Bearbeitungsmodus zu platzieren. Dadurch wird die WillBeginTableEditing-Methode ausgelöst, bei der die Zeile (neue Hinzufügen) am Ende der Tabelle angezeigt wird, die als "Einfügeschaltfläche" fungiert.
  • DidFinishTableEditing – Wenn die Schaltfläche "Fertig" berührt SetEditing wird, wird erneut aufgerufen, um den Bearbeitungsmodus zu deaktivieren. Der Beispielcode entfernt die Zeile (neue Hinzufügen) aus der Tabelle, wenn die Bearbeitung nicht mehr erforderlich ist.

Diese Methodenüberschreibungen werden in der Beispieldatei TableEditModeAdd/Code/TableSource.cs implementiert:

public override UITableViewCellEditingStyle EditingStyleForRow (UITableView tableView, NSIndexPath indexPath)
{
    if (tableView.Editing) {
        if (indexPath.Row == tableView.NumberOfRowsInSection (0) - 1)
            return UITableViewCellEditingStyle.Insert;
        else
            return UITableViewCellEditingStyle.Delete;
    } else // not in editing mode, enable swipe-to-delete for all rows
        return UITableViewCellEditingStyle.Delete;
}
public override NSIndexPath CustomizeMoveTarget (UITableView tableView, NSIndexPath sourceIndexPath, NSIndexPath proposedIndexPath)
{
    var numRows = tableView.NumberOfRowsInSection (0) - 1; // less the (add new) one
    if (proposedIndexPath.Row >= numRows)
        return NSIndexPath.FromRowSection(numRows - 1, 0);
    else
        return proposedIndexPath;
}
public override bool CanMoveRow (UITableView tableView, NSIndexPath indexPath)
{
    return indexPath.Row < tableView.NumberOfRowsInSection (0) - 1;
}

Diese beiden benutzerdefinierten Methoden werden verwendet, um die Zeile (neue Hinzufügen) hinzuzufügen und zu entfernen, wenn der Bearbeitungsmodus der Tabelle aktiviert oder deaktiviert ist:

public void WillBeginTableEditing (UITableView tableView)
{
    tableView.BeginUpdates ();
    // insert the 'ADD NEW' row at the end of table display
    tableView.InsertRows (new NSIndexPath[] {
            NSIndexPath.FromRowSection (tableView.NumberOfRowsInSection (0), 0)
        }, UITableViewRowAnimation.Fade);
    // create a new item and add it to our underlying data (it is not intended to be permanent)
    tableItems.Add (new TableItem ("(add new)"));
    tableView.EndUpdates (); // applies the changes
}
public void DidFinishTableEditing (UITableView tableView)
{
    tableView.BeginUpdates ();
    // remove our 'ADD NEW' row from the underlying data
    tableItems.RemoveAt ((int)tableView.NumberOfRowsInSection (0) - 1); // zero based :)
    // remove the row from the table display
    tableView.DeleteRows (new NSIndexPath[] { NSIndexPath.FromRowSection (tableView.NumberOfRowsInSection (0) - 1, 0) }, UITableViewRowAnimation.Fade);
    tableView.EndUpdates (); // applies the changes
}

Schließlich instanziiert dieser Code die Schaltflächen "Bearbeiten " und "Fertig " mit Lambda-Funktionen, die den Bearbeitungsmodus aktivieren oder deaktivieren, wenn sie berührt werden:

done = new UIBarButtonItem(UIBarButtonSystemItem.Done, (s,e)=>{
    table.SetEditing (false, true);
    NavigationItem.RightBarButtonItem = edit;
    tableSource.DidFinishTableEditing(table);
});
edit = new UIBarButtonItem(UIBarButtonSystemItem.Edit, (s,e)=>{
    if (table.Editing)
        table.SetEditing (false, true); // if we've half-swiped a row
    tableSource.WillBeginTableEditing(table);
    table.SetEditing (true, true);
    NavigationItem.LeftBarButtonItem = null;
    NavigationItem.RightBarButtonItem = done;
});

Dieses Ui-Muster für die Zeileneinfügung wird nicht sehr häufig verwendet, Sie können jedoch auch die UITableView.BeginUpdatesEndUpdates Einfügung oder Entfernung von Zellen in einer beliebigen Tabelle verwenden. Die Regel für die Verwendung dieser Methoden besteht darin, dass der Unterschied im Wert, der zwischen RowsInSection den BeginUpdates Aufrufen EndUpdates zurückgegeben wird, mit der Nettoanzahl der mit den InsertRows Methoden DeleteRows hinzugefügten/gelöschten Zellen übereinstimmen muss. Wenn die zugrunde liegende Datenquelle nicht geändert wird, um den Einfügungen/Löschungen in der Tabellenansicht zu entsprechen, tritt ein Fehler auf.