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.
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
pourUITableView
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é.
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.
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 retourneUITableViewCellEditingStyle.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.