Freigeben über


Auffüllen einer Tabelle mit Daten in Xamarin.iOS

Zum Hinzufügen von Zeilen zu einer UITableView Müssen Sie eine UITableViewSource Unterklasse implementieren und die Methoden überschreiben, die von der Tabellenansicht aufgerufen werden, um sich selbst aufzufüllen.

In diesem Leitfaden werden folgende Themen behandelt:

  • Unterklassen einer UITableViewSource
  • Wiederverwenden von Zellen
  • Hinzufügen eines Indexes
  • Hinzufügen von Kopf- und Fußzeilen

Unterklassen von UITableViewSource

Jeder UITableViewSource Unterklasse wird eine UITableViewUnterklasse zugewiesen. Die Tabellenansicht fragt die Quellklasse ab, um zu bestimmen, wie sie selbst gerendert werden soll (z. B. wie viele Zeilen erforderlich sind, und die Höhe jeder Zeile, wenn sie sich von der Standardeinstellung unterscheidet). Am wichtigsten ist, dass die Quelle jede Zellenansicht bereitstellt, die mit Daten gefüllt ist.

Es sind nur zwei obligatorische Methoden erforderlich, um Tabellenanzeigedaten zu erstellen:

  • RowsInSection – Gibt eine nint Anzahl der Gesamtzahl der Datenzeilen zurück, die die Tabelle anzeigen soll.
  • GetCell – Gibt eine UITableViewCell mit Daten gefüllte Daten für den entsprechenden Zeilenindex zurück, der an die Methode übergeben wird.

Die BasicTable-Beispieldatei TableSource.cs verfügt über die einfachste Implementierung von UITableViewSource. Sie können im folgenden Codeausschnitt sehen, dass es ein Array von Zeichenfolgen akzeptiert, die in der Tabelle angezeigt werden sollen, und gibt eine Standardzellenformatvorlage zurück, die jede Zeichenfolge enthält:

public class TableSource : UITableViewSource {

        string[] TableItems;
        string CellIdentifier = "TableCell";

        public TableSource (string[] items)
        {
            TableItems = items;
        }

        public override nint RowsInSection (UITableView tableview, nint section)
        {
            return TableItems.Length;
        }

        public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
        {
            UITableViewCell cell = tableView.DequeueReusableCell (CellIdentifier);
            string item = TableItems[indexPath.Row];

            //if there are no cells to reuse, create a new one
            if (cell == null)
            {
                cell = new UITableViewCell (UITableViewCellStyle.Default, CellIdentifier);
            }

            cell.TextLabel.Text = item;

            return cell;
        }
}

Eine UITableViewSource kann jede beliebige Datenstruktur verwenden, von einem einfachen Zeichenfolgenarray (wie in diesem Beispiel gezeigt) zu einer Liste <> oder einer anderen Auflistung. Die Implementierung von UITableViewSource Methoden isoliert die Tabelle aus der zugrunde liegenden Datenstruktur.

Um diese Unterklasse zu verwenden, erstellen Sie ein Zeichenfolgenarray, um die Quelle zu erstellen, und weisen Sie sie einer Instanz von UITableView:

public override void ViewDidLoad ()
{
    base.ViewDidLoad ();
    table = new UITableView(View.Bounds); // defaults to Plain style
    string[] tableItems = new string[] {"Vegetables","Fruits","Flower Buds","Legumes","Bulbs","Tubers"};
    table.Source = new TableSource(tableItems);
    Add (table);
}

Die resultierende Tabelle sieht wie folgt aus:

Beispieltabelle, die ausgeführt wird

In den meisten Tabellen kann der Benutzer eine Zeile berühren, um sie auszuwählen und eine andere Aktion auszuführen (z. B. das Wiedergeben eines Lieds oder das Aufrufen eines Kontakts oder das Anzeigen eines anderen Bildschirms). Um dies zu erreichen, müssen wir einige Dinge tun. Als Erstes erstellen wir einen AlertController, um eine Meldung anzuzeigen, wenn der Benutzer auf eine Zeile klickt, indem er der RowSelected Methode Folgendes hinzufügt:

public override void RowSelected (UITableView tableView, NSIndexPath indexPath)
{
    UIAlertController okAlertController = UIAlertController.Create ("Row Selected", tableItems[indexPath.Row], UIAlertControllerStyle.Alert);
    okAlertController.AddAction(UIAlertAction.Create("OK", UIAlertActionStyle.Default, null));
    ...

    tableView.DeselectRow (indexPath, true);
}

Erstellen Sie als Nächstes eine Instanz unseres Ansichtscontrollers:

HomeScreen owner;

Fügen Sie ihrer UITableViewSource-Klasse einen Konstruktor hinzu, der einen Ansichtscontroller als Parameter verwendet und in einem Feld speichert:

public TableSource (string[] items, HomeScreen owner)
{
    ...
    this.owner = owner;

}

Ändern Sie die ViewDidLoad-Methode, in der die UITableViewSource-Klasse erstellt wird, um den this Verweis zu übergeben:

table.Source = new TableSource(tableItems, this);

Rufen Sie PresentViewController schließlich wieder in Ihrer RowSelected Methode das zwischengespeicherte Feld auf:

public override void RowSelected (UITableView tableView, NSIndexPath indexPath)
{
    ...
    owner.PresentViewController (okAlertController, true, null);

    ...
}

Jetzt kann der Benutzer eine Zeile berühren, und eine Warnung wird angezeigt:

Die ausgewählte Zeile

Wiederverwenden von Zellen

In diesem Beispiel sind nur sechs Elemente vorhanden, daher ist keine Wiederverwendung der Zelle erforderlich. Beim Anzeigen von Hunderten oder Tausenden von Zeilen wäre es jedoch ein Speicherverschwendung, um Hunderte oder Tausende von UITableViewCell Objekten zu erstellen, wenn nur wenige gleichzeitig auf den Bildschirm passen.

Um diese Situation zu vermeiden, wird die Ansicht, wenn eine Zelle aus dem Bildschirm verschwindet, in einer Warteschlange zur Wiederverwendung platziert. Während der Benutzer scrollt, ruft die Tabelle auf GetCell , um neue Ansichten anzuzeigen – um eine vorhandene Zelle (die derzeit nicht angezeigt wird) wiederzuverwenden, rufen Sie einfach die DequeueReusableCell Methode auf. Wenn eine Zelle für die Wiederverwendung verfügbar ist, wird sie zurückgegeben, andernfalls wird ein NULL-Wert zurückgegeben, und Ihr Code muss eine neue Zelleninstanz erstellen.

Dieser Codeausschnitt aus dem Beispiel veranschaulicht das Muster:

// request a recycled cell to save memory
UITableViewCell cell = tableView.DequeueReusableCell (cellIdentifier);
// if there are no cells to reuse, create a new one
if (cell == null)
    cell = new UITableViewCell (UITableViewCellStyle.Default, cellIdentifier);

Die cellIdentifier effektive Erstellung separater Warteschlangen für verschiedene Zelltypen. In diesem Beispiel sehen alle Zellen gleich aus, sodass nur ein hartcodierter Bezeichner verwendet wird. Wenn es unterschiedliche Zelltypen gab, sollten sie jeweils über eine andere Bezeichnerzeichenfolge verfügen, sowohl wenn sie instanziiert werden als auch wenn sie aus der Wiederverwendungswarteschlange angefordert werden.

Wiederverwenden von Zellen in iOS 6+

iOS 6 hat ein Zellwiederverwendungsmuster hinzugefügt, das der ersten Einführung mit Sammlungsansichten ähnelt. Obwohl das oben gezeigte vorhandene Wiederverwendungsmuster weiterhin aus Gründen der Abwärtskompatibilität unterstützt wird, ist dieses neue Muster vorzuziehen, da es die Notwendigkeit der NULL-Überprüfung in der Zelle entfernt.

Mit dem neuen Muster registriert eine Anwendung die Zellklasse oder das XIB, die verwendet werden soll, indem sie entweder RegisterClassForCellReuse oder RegisterNibForCellReuse im Konstruktor des Controllers aufgerufen wird. Rufen DequeueReusableCell Sie dann beim Aufheben der Queue der Zelle in der GetCell Methode einfach die Übergabe des Bezeichners auf, den Sie für die Zellenklasse oder xib registriert haben, und den Indexpfad.

Der folgende Code registriert beispielsweise eine benutzerdefinierte Zellenklasse in einem UITableViewController:

public class MyTableViewController : UITableViewController
{
  static NSString MyCellId = new NSString ("MyCellId");

  public MyTableViewController ()
  {
    TableView.RegisterClassForCellReuse (typeof(MyCell), MyCellId);
  }
  ...
}

Wenn die MyCell-Klasse registriert ist, kann die Zelle in der GetCell Methode der UITableViewSource Queuierung aufgehoben werden, ohne dass die zusätzliche NULL-Prüfung erforderlich ist, wie unten dargestellt:

class MyTableSource : UITableViewSource
{
  public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
  {
    // if cell is not available in reuse pool, iOS will create one automatically
    // no need to do null check and create cell manually
    var cell = (MyCell) tableView.DequeueReusableCell (MyCellId, indexPath);

    // do whatever you need to with cell, such as assigning properties, etc.

    return cell;
  }
}

Beachten Sie folgendes: Wenn Sie das neue Wiederverwendungsmuster mit einer benutzerdefinierten Zellklasse verwenden, müssen Sie den Konstruktor implementieren, der einen IntPtr, wie im folgenden Codeausschnitt dargestellt, verwendet. Andernfalls Objective-C kann keine Instanz der Zellenklasse erstellt werden:

public class MyCell : UITableViewCell
{
  public MyCell (IntPtr p):base(p)
  {
  }
  ...
}

Beispiele der oben erläuterten Themen finden Sie im basicTable-Beispiel, das mit diesem Artikel verknüpft ist.

Hinzufügen eines Indexes

Ein Index hilft dem Benutzer, durch lange Listen zu scrollen, in der Regel alphabetisch sortiert, obwohl Sie nach den gewünschten Kriterien indiziert werden können. Das BasicTableIndex-Beispiel lädt eine viel längere Liste von Elementen aus einer Datei, um den Index zu veranschaulichen. Jedes Element im Index entspricht einem "Abschnitt" der Tabelle.

Die Indexanzeige

Um "Abschnitte" zu unterstützen, müssen die Daten hinter der Tabelle gruppiert werden, sodass das BasicTableIndex-Beispiel ein Dictionary<> aus dem Array von Zeichenfolgen erstellt, wobei der erste Buchstabe jedes Elements als Wörterbuchschlüssel verwendet wird:

indexedTableItems = new Dictionary<string, List<string>>();
foreach (var t in items) {
    if (indexedTableItems.ContainsKey (t[0].ToString ())) {
        indexedTableItems[t[0].ToString ()].Add(t);
    } else {
        indexedTableItems.Add (t[0].ToString (), new List<string>() {t});
    }
}
keys = indexedTableItems.Keys.ToArray ();

Die UITableViewSource Unterklasse benötigt dann die folgenden Methoden, die hinzugefügt oder geändert werden, um folgendes Dictionary<> zu verwenden:

  • NumberOfSections – diese Methode ist optional, standardmäßig geht die Tabelle von einem Abschnitt aus. Bei der Anzeige eines Indexes sollte diese Methode die Anzahl der Elemente im Index zurückgeben (z. B. 26, wenn der Index alle Buchstaben des englischen Alphabets enthält).
  • RowsInSection – gibt die Anzahl der Zeilen in einem bestimmten Abschnitt zurück.
  • SectionIndexTitles – gibt das Array von Zeichenfolgen zurück, die zum Anzeigen des Indexes verwendet werden. Der Beispielcode gibt ein Array von Buchstaben zurück.

Die aktualisierten Methoden in der Beispieldatei BasicTableIndex/TableSource.cs sehen wie folgt aus:

public override nint NumberOfSections (UITableView tableView)
{
    return keys.Length;
}
public override nint RowsInSection (UITableView tableview, nint section)
{
    return indexedTableItems[keys[section]].Count;
}
public override string[] SectionIndexTitles (UITableView tableView)
{
    return keys;
}

Indizes werden in der Regel nur mit der Formatvorlage "Nur-Tabelle" verwendet.

Hinzufügen von Kopf- und Fußzeilen

Kopf- und Fußzeilen können verwendet werden, um Zeilen in einer Tabelle visuell zu gruppieren. Die erforderliche Datenstruktur ist sehr ähnlich wie das Hinzufügen eines Indexes – eine Dictionary<> sehr gut funktioniert. Anstatt das Alphabet zum Gruppieren der Zellen zu verwenden, wird in diesem Beispiel das Gemüse nach botanischem Typ gruppiert. Die Ausgabe sieht wie folgt aus:

Beispielkopf- und Fußzeilen

Zum Anzeigen von Kopf- und Fußzeilen erfordert die UITableViewSource Unterklasse die folgenden zusätzlichen Methoden:

  • TitleForHeader – gibt den Text zurück, der als Kopfzeile verwendet werden soll.
  • TitleForFooter – gibt den Text zurück, der als Fußzeile verwendet werden soll.

Die aktualisierten Methoden in der Beispieldatei BasicTableHeaderFooter/Code/TableSource.cs wie folgt aussehen:

public override string TitleForHeader (UITableView tableView, nint section)
{
    return keys[section];
}
public override string TitleForFooter (UITableView tableView, nint section)
{
    return indexedTableItems[keys[section]].Count + " items";
}

Sie können die Darstellung der Kopf- und Fußzeile mit einem View-Objekt mithilfe der GetViewForHeader Außerkraftsetzungen UITableViewSourceund GetViewForFooter Methoden weiter anpassen.