Partager via


Modification de tables avec Xamarin.iOS

Les fonctionnalités d’édition de table sont activées en substituant des méthodes dans une UITableViewSource sous-classe. Le comportement d’édition le plus simple est le mouvement de balayage à supprimer qui peut être implémenté avec un remplacement de méthode unique. Une modification plus complexe (y compris le déplacement de lignes) peut être effectuée avec la table en mode édition.

Balayez pour supprimer

La fonctionnalité de balayage pour supprimer est un mouvement naturel dans iOS attendu par les utilisateurs.

Exemple de balayage vers supprimer

Il existe trois remplacements de méthode qui affectent le mouvement de balayage pour afficher un bouton Supprimer dans une cellule :

  • CommitEditingStyle : la source de la table détecte si cette méthode est remplacée et active automatiquement le mouvement de balayage à supprimer. L’implémentation de la méthode doit appeler DeleteRows pour UITableView que les cellules disparaissent et suppriment également les données sous-jacentes de votre modèle (par exemple, un tableau, un dictionnaire ou une base de données).
  • CanEditRow : si CommitEditingStyle est substitué, toutes les lignes sont supposées être modifiables. Si cette méthode est implémentée et retourne false (pour certaines lignes spécifiques ou pour toutes les lignes), le mouvement de balayage à supprimer n’est pas disponible dans cette cellule.
  • TitleForDeleteConfirmation : spécifie éventuellement le texte du bouton Supprimer . Si cette méthode n’est pas implémentée, le texte du bouton est « Delete ».

Ces méthodes sont implémentées dans la TableSource classe suivante :

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 + ")";
}

Pour cet exemple, la UITableViewSource mise à jour a été effectuée pour utiliser un List<TableItem> (au lieu d’un tableau de chaînes) comme source de données, car elle prend en charge l’ajout et la suppression d’éléments de la collection.

Mode d’édition

Lorsqu’une table est en mode édition, l’utilisateur voit un widget rouge « arrêter » sur chaque ligne, qui affiche un bouton Supprimer lorsqu’il est tactile. Le tableau affiche également une icône « handle » pour indiquer que la ligne peut être déplacée pour modifier l’ordre. L’exemple TableEditMode implémente ces fonctionnalités comme indiqué.

L’exemple TableEditMode implémente ces fonctionnalités, comme indiqué

Plusieurs méthodes UITableViewSource affectent le comportement du mode d’édition d’une table :

  • CanEditRow : indique si chaque ligne peut être modifiée. Retourne la valeur false pour empêcher les deux mouvements de balayage à supprimer et de suppression en mode Édition.
  • CanMoveRow : retourne la valeur true pour activer le déplacement « handle » ou false pour empêcher le déplacement.
  • EditingStyleForRow : lorsque la table est en mode édition, la valeur de retour de cette méthode détermine si la cellule affiche l’icône de suppression rouge ou l’icône d’ajout vert. Retourne UITableViewCellEditingStyle.None si la ligne ne doit pas être modifiable.
  • MoveRow : appelé lorsqu’une ligne est déplacée afin que la structure de données sous-jacente puisse être modifiée pour correspondre aux données telles qu’elles sont affichées dans la table.

L’implémentation des trois premières méthodes est relativement simple, sauf si vous souhaitez utiliser le indexPath comportement des lignes spécifiques, il vous suffit de coder en dur les valeurs de retour pour l’ensemble de la table.

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
}

L’implémentation MoveRow est un peu plus compliquée, car elle doit modifier la structure de données sous-jacente pour qu’elle corresponde à la nouvelle commande. Étant donné que les données sont implémentées en tant que List code ci-dessous supprime l’élément de données à son ancien emplacement et l’insère au nouvel emplacement. Si les données ont été stockées dans une table de base de données SQLite avec une colonne « order » (par exemple), cette méthode doit plutôt effectuer certaines opérations SQL pour réorganiser les nombres de cette colonne.

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);
}

Enfin, pour obtenir la table en mode édition, le bouton Modifier doit appeler SetEditing comme ceci

table.SetEditing (true, true);

et lorsque l’utilisateur a terminé la modification, le bouton Terminé doit désactiver le mode d’édition :

table.SetEditing (false, true);

Style d’édition d’insertion de ligne

L’insertion de lignes à partir de la table est une interface utilisateur rare : l’exemple principal dans les applications iOS standard est l’écran Modifier le contact . Cette capture d’écran montre comment fonctionne la fonctionnalité d’insertion de ligne : en mode édition, il existe une ligne supplémentaire qui (quand un clic) insère des lignes supplémentaires dans les données. Une fois la modification terminée, la ligne temporaire (ajouter un nouveau) est supprimée.

Une fois la modification terminée, l’ajout temporaire d’une nouvelle ligne est supprimé

Il existe plusieurs méthodes différentes qui UITableViewSource affectent le comportement du mode d’édition d’une table. Ces méthodes ont été implémentées comme suit dans l’exemple de code :

  • EditingStyleForRow : retourne UITableViewCellEditingStyle.Delete les lignes contenant des données et retourne UITableViewCellEditingStyle.Insert la dernière ligne (qui sera ajoutée spécifiquement pour se comporter en tant que bouton d’insertion).
  • CustomizeMoveTarget : pendant que l’utilisateur déplace une cellule, la valeur de retour de cette méthode facultative peut remplacer son choix d’emplacement. Cela signifie que vous pouvez les empêcher de « supprimer » la cellule dans certaines positions, comme cet exemple qui empêche tout déplacement de ligne après la ligne (ajouter une nouvelle ).
  • CanMoveRow : retourne la valeur true pour activer le déplacement « handle » ou false pour empêcher le déplacement. Dans l’exemple, la dernière ligne comporte le déplacement « handle » masqué, car il est destiné à serveur en tant que bouton d’insertion uniquement.

Nous ajoutons également deux méthodes personnalisées pour ajouter la ligne « insert », puis la supprimer à nouveau lorsqu’elle n’est plus nécessaire. Ils sont appelés à partir des boutons Modifier et Terminé :

  • WillBeginTableEditing : lorsque le bouton Modifier est touché, il appelle SetEditing pour placer la table en mode Édition. Cela déclenche la méthode WillBeginTableEditing où nous affichons la ligne (ajouter une nouvelle) à la fin de la table pour agir comme un « bouton Insérer ».
  • DidFinishTableEditing : lorsque le bouton Terminé est à nouveau appelé SetEditing pour désactiver le mode d’édition. L’exemple de code supprime la ligne (ajouter nouveau) de la table lorsque la modification n’est plus nécessaire.

Ces remplacements de méthode sont implémentés dans l’exemple de fichier TableEditModeAdd/Code/TableSource.cs :

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;
}

Ces deux méthodes personnalisées sont utilisées pour ajouter et supprimer la ligne (ajouter une nouvelle) lorsque le mode d’édition du tableau est activé ou désactivé :

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
}

Enfin, ce code instancie les boutons Modifier et Terminé , avec des lambdas qui activent ou désactivent le mode d’édition lorsqu’ils sont tactiles :

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;
});

Ce modèle d’interface utilisateur d’insertion de ligne n’est pas utilisé très souvent, mais vous pouvez également utiliser les méthodes et EndUpdates les UITableView.BeginUpdates méthodes pour animer l’insertion ou la suppression de cellules dans n’importe quel tableau. La règle d’utilisation de ces méthodes est que la différence de valeur retournée entre RowsInSection les appels et EndUpdates les BeginUpdates appels doit correspondre au nombre net de cellules ajoutées/supprimées avec les méthodes et DeleteRows méthodesInsertRows. Si la source de données sous-jacente n’est pas modifiée pour correspondre aux insertions/suppressions dans la vue de table, une erreur se produit.