Udostępnij za pośrednictwem


Wypełnianie tabeli danymi na platformie Xamarin.iOS

Aby dodać wiersze do klasy UITableView , należy zaimplementować podklasę UITableViewSource i zastąpić metody wywoływane przez widok tabeli w celu wypełnienia się.

Ten przewodnik obejmuje:

  • Podklasowanie elementu UITableViewSource
  • Ponowne użycie komórki
  • Dodawanie indeksu
  • Dodawanie nagłówków i stopek

Podklasowanie UITableViewSource

Do UITableViewSource każdej klasy jest przypisywana podklasa UITableView. Widok tabeli wykonuje zapytanie względem klasy źródłowej, aby określić, jak się renderować (na przykład ile wierszy jest wymaganych i wysokość każdego wiersza, jeśli różni się od domyślnego). Co najważniejsze, źródło dostarcza każdy widok komórki wypełniony danymi.

Istnieją tylko dwie obowiązkowe metody wymagane do utworzenia danych wyświetlania tabeli:

  • RowsInSection — zwraca liczbę nint łącznej liczby wierszy danych, które powinny być wyświetlane w tabeli.
  • GetCell — zwraca UITableViewCell dane dla odpowiedniego indeksu wiersza przekazanego do metody .

Przykładowy plik BasicTable TableSource.cs ma najprostszą możliwą implementację .UITableViewSource W poniższym fragmencie kodu widać, że akceptuje tablicę ciągów do wyświetlenia w tabeli i zwraca domyślny styl komórki zawierający każdy ciąg:

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

Obiekt UITableViewSource może używać dowolnej struktury danych z prostej tablicy ciągów (jak pokazano w tym przykładzie) do listy <> lub innej kolekcji. Implementacja UITableViewSource metod izoluje tabelę od podstawowej struktury danych.

Aby użyć tej podklasy, utwórz tablicę ciągów, aby skonstruować źródło, a następnie przypisz ją do wystąpienia klasy 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);
}

Wynikowa tabela wygląda następująco:

Przykładowa tabela uruchomiona

Większość tabel umożliwia użytkownikowi dotknięcie wiersza, aby go zaznaczyć i wykonać inną akcję (np. odtwarzanie utworu lub wywoływanie kontaktu lub wyświetlanie innego ekranu). Aby to osiągnąć, musimy zrobić kilka rzeczy. Najpierw utwórzmy element AlertController, aby wyświetlić komunikat, gdy użytkownik kliknie wiersz, dodając następujący kod do RowSelected metody :

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

Następnie utwórz wystąpienie kontrolera widoku:

HomeScreen owner;

Dodaj konstruktor do klasy UITableViewSource, który przyjmuje kontroler widoku jako parametr i zapisuje go w polu:

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

}

Zmodyfikuj metodę ViewDidLoad, w której jest tworzona klasa UITableViewSource, aby przekazać this odwołanie:

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

Na koniec ponownie w metodzie RowSelected wywołaj PresentViewController pole buforowane:

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

    ...
}

Teraz użytkownik może dotknąć wiersza i pojawi się alert:

Wybrany alert wiersza

Ponowne użycie komórki

W tym przykładzie istnieje tylko sześć elementów, więc nie jest wymagane ponowne użycie komórki. Podczas wyświetlania setek lub tysięcy wierszy byłoby to jednak strata pamięci do utworzenia setek lub tysięcy UITableViewCell obiektów, gdy tylko kilka zmieści się na ekranie naraz.

Aby uniknąć takiej sytuacji, gdy komórka zniknie z ekranu, jego widok zostanie umieszczony w kolejce do ponownego użycia. Gdy użytkownik przewija tabelę, wywołuje żądanie GetCell wyświetlenia nowych widoków — aby ponownie użyć istniejącej komórki (która nie jest obecnie wyświetlana) po prostu wywołaj metodę DequeueReusableCell . Jeśli komórka jest dostępna do ponownego użycia, zostanie zwrócona, w przeciwnym razie zostanie zwrócona wartość null, a kod musi utworzyć nowe wystąpienie komórki.

Ten fragment kodu z przykładu przedstawia wzorzec:

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

Efektywnie cellIdentifier tworzy oddzielne kolejki dla różnych typów komórek. W tym przykładzie wszystkie komórki wyglądają tak samo, więc jest używany tylko jeden zakodowany na stałe identyfikator. Jeśli istnieją różne typy komórek, każdy z nich powinien mieć inny ciąg identyfikatora, zarówno w przypadku utworzenia wystąpienia, jak i żądania z kolejki ponownego użycia.

Ponowne używanie komórek w systemie iOS 6 lub nowszym

System iOS 6 dodał wzorzec ponownego użycia komórek podobny do tego, który wprowadzono w widokach kolekcji. Mimo że istniejący wzorzec ponownego użycia pokazany powyżej jest nadal obsługiwany w celu zapewnienia zgodności z poprzednimi wersjami, ten nowy wzorzec jest preferowany, ponieważ eliminuje potrzebę sprawdzania wartości null w komórce.

Przy użyciu nowego wzorca aplikacja rejestruje klasę komórek lub xib, która ma być używana przez wywołanie RegisterClassForCellReuse konstruktora kontrolera lub RegisterNibForCellReuse . Następnie podczas kolejkowania komórki w GetCell metodzie po prostu wywołaj DequeueReusableCell przekazanie identyfikatora zarejestrowanego dla klasy komórki lub xib i ścieżki indeksu.

Na przykład poniższy kod rejestruje niestandardową klasę komórek w UITableViewController:

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

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

Po zarejestrowaniu klasy MyCell komórka może zostać w kolejce w GetCell metodzie UITableViewSource bez konieczności dodatkowego sprawdzania wartości null, jak pokazano poniżej:

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

Należy pamiętać, że w przypadku używania nowego wzorca ponownego użycia z niestandardową klasą komórek należy zaimplementować konstruktor, który przyjmuje IntPtrelement , jak pokazano w poniższym fragmencie kodu, w przeciwnym razie Objective-C nie będzie można utworzyć wystąpienia klasy komórek:

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

Przykłady tematów opisanych powyżej można znaleźć w przykładzie BasicTable połączonym z tym artykułem.

Dodawanie indeksu

Indeks pomaga użytkownikowi przewijać długie listy, zwykle uporządkowane alfabetycznie, chociaż można indeksować według dowolnych kryteriów. Przykład BasicTableIndex ładuje znacznie dłuższą listę elementów z pliku w celu zademonstrowania indeksu. Każdy element w indeksie odpowiada "sekcji" tabeli.

Wyświetlanie indeksu

Aby obsługiwać "sekcje", należy pogrupować dane w tabeli, więc przykład BasicTableIndex tworzy obiekt Dictionary<> z tablicy ciągów przy użyciu pierwszej litery każdego elementu jako klucza słownika:

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

Następnie podklasa wymaga dodania UITableViewSource lub zmodyfikowania następujących metod w celu użycia klasy Dictionary<> :

  • NumberOfSections — ta metoda jest opcjonalna, domyślnie tabela zakłada jedną sekcję. Podczas wyświetlania indeksu ta metoda powinna zwrócić liczbę elementów w indeksie (na przykład 26, jeśli indeks zawiera wszystkie litery alfabetu angielskiego).
  • RowsInSection — zwraca liczbę wierszy w danej sekcji.
  • SectionIndexTitles — zwraca tablicę ciągów, które będą używane do wyświetlania indeksu. Przykładowy kod zwraca tablicę liter.

Zaktualizowane metody w przykładowym pliku BasicTableIndex/TableSource.cs wyglądają następująco:

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

Indeksy są zwykle używane tylko w stylu zwykłej tabeli.

Dodawanie nagłówków i stopek

Nagłówki i stopki mogą służyć do wizualnego grupowania wierszy w tabeli. Wymagana struktura danych jest bardzo podobna do dodawania indeksu — Dictionary<> działa naprawdę dobrze. Zamiast używać alfabetu do grupowania komórek, ten przykład pogrupuje warzywa według typu botanicznego. Dane wyjściowe wyglądają następująco:

Przykładowe nagłówki i stopki

Aby wyświetlić nagłówki i stopki, podklasa UITableViewSource wymaga następujących dodatkowych metod:

  • TitleForHeader — zwraca tekst do użycia jako nagłówek
  • TitleForFooter — zwraca tekst, który ma być używany jako stopka.

Zaktualizowane metody w przykładowym pliku BasicTableHeaderFooter/Code/TableSource.cs wyglądają następująco:

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

Możesz dodatkowo dostosować wygląd nagłówka i stopki za pomocą obiektu View, używając GetViewForHeader przesłonięć metod i GetViewForFooter w pliku UITableViewSource.