Tabellenansichten in Xamarin.Mac

In diesem Artikel wird die Arbeit mit Tabellenansichten in einer Xamarin.Mac-Anwendung behandelt. Es beschreibt das Erstellen von Tabellenansichten im Xcode- und Schnittstellen-Generator und die Interaktion mit ihnen im Code.

Beim Arbeiten mit C# und .NET in einer Xamarin.Mac-Anwendung haben Sie Zugriff auf die gleichen Tabellenansichten, in Objective-C denen ein Entwickler arbeitet und Xcode ausführt. Da Xamarin.Mac direkt in Xcode integriert wird, können Sie den Schnittstellen-Generator von Xcode verwenden, um Ihre Tabellenansichten zu erstellen und zu Standard (oder optional direkt im C#-Code zu erstellen).

In einer Tabellenansicht werden Daten in einem tabellarischen Format angezeigt, das mindestens eine Spalte mit Informationen in mehreren Zeilen enthält. Basierend auf dem Typ der erstellten Tabellenansicht kann der Benutzer nach Spalte sortieren, Spalten neu organisieren, Spalten hinzufügen, Spalten entfernen oder die in der Tabelle enthaltenen Daten bearbeiten.

Beispieltabelle

In diesem Artikel behandeln wir die Grundlagen der Arbeit mit Tabellenansichten in einer Xamarin.Mac-Anwendung. Es wird dringend empfohlen, dass Sie zuerst den Artikel "Hello, Mac " durcharbeiten, insbesondere die Abschnitte "Einführung in Xcode" und "Interface Builder " und "Outlets" und "Actions ", da es sich um wichtige Konzepte und Techniken handelt, die wir in diesem Artikel verwenden werden.

Möglicherweise möchten Sie sich auch die Verfügbarmachen von C#-Klassen /-Methoden imObjective-CAbschnitt des Xamarin.Mac Internals-Dokuments ansehen, und es werden die befehle Export erläutert, die Register zum Verketten Ihrer C#-Klassen mit Objective-C Objekten und UI-Elementen verwendet werden.

Einführung in Tabellenansichten

In einer Tabellenansicht werden Daten in einem tabellarischen Format angezeigt, das mindestens eine Spalte mit Informationen in mehreren Zeilen enthält. Tabellenansichten werden innerhalb von Bildlaufansichten (NSScrollView) angezeigt und beginnend mit macOS 10.7 können Sie anstelle NSView von Zellen (NSCell) sowohl Zeilen als auch Spalten anzeigen. Das heißt, Sie können weiterhin verwenden NSCell , sie können jedoch in der Regel Unterklassen NSTableCellView verwenden und Ihre benutzerdefinierten Zeilen und Spalten erstellen.

Eine Tabellenansicht speichert keine eigenen Daten, sondern basiert auf einer Datenquelle (NSTableViewDataSource), um sowohl die erforderlichen Zeilen als auch Spalten auf bedarfsbezogener Basis bereitzustellen.

Das Verhalten einer Tabellenansicht kann angepasst werden, indem eine Unterklasse des Tabellenansichtsdelegats (NSTableViewDelegate) zur Unterstützung der Tabellenspaltenverwaltung, der Typ zum Auswählen von Funktionen, Zeilenauswahl und -bearbeitung, benutzerdefinierten Nachverfolgung und benutzerdefinierten Ansichten für einzelne Spalten und Zeilen bereitgestellt wird.

Beim Erstellen von Tabellenansichten schlägt Apple Folgendes vor:

  • Zulassen, dass der Benutzer die Tabelle sortieren kann, indem er auf eine Spaltenüberschrift klickt.
  • Erstellen Sie Spaltenüberschriften, die Nomen oder kurze Substantivausdrücke sind, die die in dieser Spalte angezeigten Daten beschreiben.

Weitere Informationen finden Sie im Abschnitt "Inhaltsansichten" der Os X Human Interface-Richtlinien von Apple.

Erstellen und Verwalten von Tabellenansichten in Xcode

Wenn Sie eine neue Xamarin.Mac Cocoa-Anwendung erstellen, erhalten Sie standardmäßig ein standardmäßig leeres Fenster. Diese Fenster werden in einer .storyboard Datei definiert, die automatisch im Projekt enthalten ist. Doppelklicken Sie zum Bearbeiten des Fensterentwurfs im Projektmappen-Explorer auf die Main.storyboard Datei:

Auswählen des Standard Storyboards

Dadurch wird das Fensterdesign im Schnittstellen-Generator von Xcode geöffnet:

Bearbeiten der Benutzeroberfläche in Xcode

Geben Sie table in das Suchfeld des Bibliotheksinspektors ein, um das Auffinden der Tabellenansichtssteuerelemente zu vereinfachen:

Auswählen einer Tabellenansicht aus der Bibliothek

Ziehen Sie eine Tabellenansicht auf den Ansichtscontroller im Schnittstellen-Editor, füllen Sie den Inhaltsbereich des Ansichtscontrollers aus, und legen Sie sie so fest, dass sie verkleinern und mit dem Fenster im Einschränkungs-Editor wächst:

Bearbeitungseinschränkungen

Wählen Sie die Tabellenansicht in der Schnittstellenhierarchie aus, und die folgenden Eigenschaften sind im Attributinspektor verfügbar:

Screenshot der eigenschaften, die im Attributinspektor verfügbar sind.

  • Inhaltsmodus : Ermöglicht Ihnen die Verwendung von Ansichten (NSView) oder Zellen (NSCell) zum Anzeigen der Daten in den Zeilen und Spalten. Ab macOS 10.7 sollten Sie Ansichten verwenden.
  • Floats Group Rows - If true, the Table View will draw grouped cells as if they are floating.
  • Spalten – Definiert die Anzahl der angezeigten Spalten.
  • Kopfzeilen – Wenn true, haben die Spalten Kopfzeilen.
  • Neuanordnung – Wenn true, kann der Benutzer die Spalten in der Tabelle neu anordnen.
  • Größenänderung – Wenn true, kann der Benutzer Spaltenüberschriften ziehen, um die Größe von Spalten zu ändern.
  • Spaltengröße – Steuert, wie die Tabelle Spalten automatisch größe.
  • Hervorhebung – Steuert den Typ der Hervorhebung der Tabelle, die beim Auswählen einer Zelle verwendet wird.
  • Alternative Zeilen – Wenn trueeine andere Zeile jemals eine andere Hintergrundfarbe aufweist.
  • Horizontales Raster – Wählt den Typ des Rahmens aus, der zwischen Zellen horizontal gezeichnet wird.
  • Vertikales Raster – Wählt den Typ des Rahmens aus, der vertikal zwischen Zellen gezeichnet wird.
  • Rasterfarbe – Legt die Zellenrahmenfarbe fest.
  • Hintergrund – Legt die Hintergrundfarbe der Zelle fest.
  • Auswahl – Ermöglicht Ihnen zu steuern, wie der Benutzer Zellen in der Tabelle auswählen kann:
    • Mehrfach – Wenn true, kann der Benutzer mehrere Zeilen und Spalten auswählen.
    • Spalte – Wenn trueder Benutzer Spalten auswählen kann.
    • Type Select - If true, the user can type a character to select a row.
    • Leer – Wenn trueder Benutzer keine Zeile oder Spalte auswählen muss, lässt die Tabelle überhaupt keine Auswahl zu.
  • Automatisches Speichern – Der Name, unter dem das Tabellenformat automatisch gespeichert wird.
  • Spalteninformationen – Wenn true, wird die Reihenfolge und Breite der Spalten automatisch gespeichert.
  • Zeilenumbrüche – Wählen Sie aus, wie die Zelle Zeilenumbrüche behandelt.
  • Letzte sichtbare Linie abgeschnitten – Wenn truedie Zelle in den Daten abgeschnitten wird, kann sie nicht in die Grenzen passen.

Wichtig

Sofern Sie keine ältere Xamarin.Mac-Anwendung Standard beibehalten, NSView sollten basierende Tabellenansichten über NSCell basierte Tabellenansichten verwendet werden. NSCell wird als Legacy betrachtet und wird möglicherweise in Zukunft nicht unterstützt.

Wählen Sie eine Tabellenspalte in der Schnittstellenhierarchie aus, und die folgenden Eigenschaften sind im Attributinspektor verfügbar:

Der Screenshot zeigt die Eigenschaften, die für eine Tabellenspalte im Attributinspektor verfügbar sind.

  • Titel – Legt den Titel der Spalte fest.
  • Ausrichtung – Legen Sie die Ausrichtung des Texts innerhalb der Zellen fest.
  • Titelschriftart – Wählt die Schriftart für den Kopfzeilentext der Zelle aus.
  • Sortierschlüssel – Ist der Schlüssel, der zum Sortieren von Daten in der Spalte verwendet wird. Lassen Sie es leer, wenn der Benutzer diese Spalte nicht sortieren kann.
  • Auswahl – Ist die Aktion, die zum Ausführen der Sortierung verwendet wird. Lassen Sie es leer, wenn der Benutzer diese Spalte nicht sortieren kann.
  • Reihenfolge – Ist die Sortierreihenfolge für die Spaltendaten.
  • Größenänderung – Wählt den Typ der Größenänderung für die Spalte aus.
  • Bearbeitbar – Wenn true, kann der Benutzer Zellen in einer zellenbasierten Tabelle bearbeiten.
  • Ausgeblendet – Wenn true, ist die Spalte ausgeblendet.

Sie können auch die Größe der Spalte ändern, indem Sie den Ziehpunkt (vertikal zentriert auf der rechten Seite der Spalte) nach links oder rechts ziehen.

Wählen wir die einzelnen Spalten in der Tabellenansicht aus, und geben Sie der ersten Spalte einen Titel und Product die zweite DetailsSpalte.

Wählen Sie eine Tabellenzellenansicht (NSTableViewCell) in der Schnittstellenhierarchie aus, und die folgenden Eigenschaften sind im Attributinspektor verfügbar:

Screenshot zeigt die Eigenschaften, die für eine Tabellenzellenansicht im Attributinspektor verfügbar sind.

Dies sind alle Eigenschaften einer Standardansicht. Sie haben auch die Möglichkeit, die Größe der Zeilen für diese Spalte hier zu ändern.

Wählen Sie eine Tabellenansichtszelle (standardmäßig ist dies ein NSTextField) in der Schnittstellenhierarchie aus, und die folgenden Eigenschaften sind im Attributinspektor verfügbar:

Screenshot zeigt die Eigenschaften, die für eine Tabellenansichtszelle im Attributinspektor verfügbar sind.

Hier werden alle Eigenschaften eines Standardtextfelds festgelegt. Standardmäßig wird ein Standardtextfeld verwendet, um Daten für eine Zelle in einer Spalte anzuzeigen.

Wählen Sie eine Tabellenzellenansicht (NSTableFieldCell) in der Schnittstellenhierarchie aus, und die folgenden Eigenschaften sind im Attributinspektor verfügbar:

Der Screenshot zeigt die Eigenschaften, die für eine andere Tabellenansichtszelle im Attributinspektor verfügbar sind.

Die wichtigsten Einstellungen sind hier:

  • Layout – Wählen Sie aus, wie Zellen in dieser Spalte angeordnet sind.
  • Verwendet den Einzelzeilenmodus – Wenn true, ist die Zelle auf eine einzelne Zeile beschränkt.
  • First Runtime Layout Width - If true, the cell will prefer the width set for it (either manually or automatically) when it is displayed the first time the application is run.
  • Aktion – Steuert, wenn die Bearbeitungsaktion für die Zelle gesendet wird.
  • Verhalten – Definiert, ob eine Zelle auswählbar oder bearbeitbar ist.
  • Rich Text – Wenn true, kann die Zelle formatierten und formatierten Text anzeigen.
  • Rückgängig – Wenntrue, übernimmt die Zelle die Verantwortung für das Rückgängig-Verhalten.

Wählen Sie die Tabellenzellenansicht (NSTableFieldCell) unten in einer Tabellenspalte in der Schnittstellenhierarchie aus:

Auswählen der Tabellenzellenansicht

Auf diese Weise können Sie die Tabellenzellenansicht bearbeiten, die als Basismuster für alle Zellen verwendet wird, die für die angegebene Spalte erstellt wurden.

Hinzufügen von Aktionen und Verkaufsstellen

Genau wie jedes andere Kakao-UI-Steuerelement müssen wir unsere Tabellenansicht verfügbar machen, und es sind Spalten und Zellen mit C#-Code mithilfe von Aktionen und Outlets (basierend auf der erforderlichen Funktionalität).

Der Vorgang ist für jedes Tabellenansichtselement identisch, das verfügbar gemacht werden soll:

  1. Wechseln Sie zum Assistenten-Editor , und stellen Sie sicher, dass die ViewController.h Datei ausgewählt ist:

    Der Assistent-Editor

  2. Wählen Sie die Tabellenansicht aus der Schnittstellenhierarchie aus, klicken Sie, und ziehen Sie es in die ViewController.h Datei.

  3. Erstellen Sie eine Steckdose für die Tabellenansicht namens ProductTable:

    Screenshot einer Steckdose, die für die Tabellenansicht mit dem Namen

  4. Erstellen Sie Outlets für die Tabellenspalten, wie auch genannt ProductColumn , und DetailsColumn:

    Screenshot zeigt eine Steckdose, die für andere Tabellenansichten erstellt wurde.

  5. Speichern Sie Änderungen, und kehren Sie zu Visual Studio für Mac zurück, um mit Xcode zu synchronisieren.

Als Nächstes schreiben wir den Code, der einige Daten für die Tabelle anzeigt, wenn die Anwendung ausgeführt wird.

Auffüllen der Tabellenansicht

Mit unserer Tabellenansicht, die im Schnittstellen-Generator entwickelt und über einen Steckdose verfügbar gemacht wird, müssen wir als Nächstes den C#-Code erstellen, um ihn aufzufüllen.

Als Erstes erstellen wir eine neue Product Klasse, um die Informationen für die einzelnen Zeilen zu enthalten. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt, und wählen Sie "Neue Datei hinzufügen>" aus... Wählen Sie "Allgemein>leere Klasse" aus, geben Sie Productden Namen ein, und klicken Sie auf die Schaltfläche "Neu":

Erstellen einer leeren Klasse

Stellen Sie sicher, dass die Product.cs Datei wie folgt aussieht:

using System;

namespace MacTables
{
  public class Product
  {
    #region Computed Properties
    public string Title { get; set;} = "";
    public string Description { get; set;} = "";
    #endregion

    #region Constructors
    public Product ()
    {
    }

    public Product (string title, string description)
    {
      this.Title = title;
      this.Description = description;
    }
    #endregion
  }
}

Als Nächstes müssen wir eine Unterklasse erstellen, mit NSTableDataSource der die Daten für unsere Tabelle bereitgestellt werden, wie sie angefordert werden. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt, und wählen Sie "Neue Datei hinzufügen>" aus... Wählen Sie "Allgemein>leere Klasse" aus, geben Sie ProductTableDataSource den Namen ein, und klicken Sie auf die Schaltfläche "Neu".

Bearbeiten Sie die ProductTableDataSource.cs Datei, und stellen Sie sicher, dass sie wie folgt aussieht:

using System;
using AppKit;
using CoreGraphics;
using Foundation;
using System.Collections;
using System.Collections.Generic;

namespace MacTables
{
  public class ProductTableDataSource : NSTableViewDataSource
  {
    #region Public Variables
    public List<Product> Products = new List<Product>();
    #endregion

    #region Constructors
    public ProductTableDataSource ()
    {
    }
    #endregion

    #region Override Methods
    public override nint GetRowCount (NSTableView tableView)
    {
      return Products.Count;
    }
    #endregion
  }
}

Diese Klasse verfügt über Speicher für die Elemente der Tabellenansicht und setzt die GetRowCount Anzahl der Zeilen in der Tabelle außer Kraft.

Schließlich müssen wir eine Unterklasse erstellen, die NSTableDelegate das Verhalten für unsere Tabelle bereitstellt. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt, und wählen Sie "Neue Datei hinzufügen>" aus... Wählen Sie "Allgemein>leere Klasse" aus, geben Sie ProductTableDelegate den Namen ein, und klicken Sie auf die Schaltfläche "Neu".

Bearbeiten Sie die ProductTableDelegate.cs Datei, und stellen Sie sicher, dass sie wie folgt aussieht:

using System;
using AppKit;
using CoreGraphics;
using Foundation;
using System.Collections;
using System.Collections.Generic;

namespace MacTables
{
  public class ProductTableDelegate: NSTableViewDelegate
  {
    #region Constants
    private const string CellIdentifier = "ProdCell";
    #endregion

    #region Private Variables
    private ProductTableDataSource DataSource;
    #endregion

    #region Constructors
    public ProductTableDelegate (ProductTableDataSource datasource)
    {
      this.DataSource = datasource;
    }
    #endregion

    #region Override Methods
    public override NSView GetViewForItem (NSTableView tableView, NSTableColumn tableColumn, nint row)
    {
      // This pattern allows you reuse existing views when they are no-longer in use.
      // If the returned view is null, you instance up a new view
      // If a non-null view is returned, you modify it enough to reflect the new data
      NSTextField view = (NSTextField)tableView.MakeView (CellIdentifier, this);
      if (view == null) {
        view = new NSTextField ();
        view.Identifier = CellIdentifier;
        view.BackgroundColor = NSColor.Clear;
        view.Bordered = false;
        view.Selectable = false;
        view.Editable = false;
      }

      // Setup view based on the column selected
      switch (tableColumn.Title) {
      case "Product":
        view.StringValue = DataSource.Products [(int)row].Title;
        break;
      case "Details":
        view.StringValue = DataSource.Products [(int)row].Description;
        break;
      }

      return view;
    }
    #endregion
  }
}

Beim Erstellen einer Instanz des ProductTableDelegateElements übergeben wir auch eine Instanz der ProductTableDataSource Tabelle, die die Daten für die Tabelle bereitstellt. Die GetViewForItem Methode ist dafür verantwortlich, eine Ansicht (Daten) zurückzugeben, um die Zelle für eine Spalte und Zeile anzuzeigen. Wenn möglich, wird eine vorhandene Ansicht wiederverwendet, um die Zelle anzuzeigen, wenn keine neue Ansicht erstellt werden muss.

Wenn Sie die Tabelle auffüllen möchten, bearbeiten wir die ViewController.cs Datei, und lassen Sie die AwakeFromNib Methode wie folgt aussehen:

public override void AwakeFromNib ()
{
  base.AwakeFromNib ();

  // Create the Product Table Data Source and populate it
  var DataSource = new ProductTableDataSource ();
  DataSource.Products.Add (new Product ("Xamarin.iOS", "Allows you to develop native iOS Applications in C#"));
  DataSource.Products.Add (new Product ("Xamarin.Android", "Allows you to develop native Android Applications in C#"));
  DataSource.Products.Add (new Product ("Xamarin.Mac", "Allows you to develop Mac native Applications in C#"));

  // Populate the Product Table
  ProductTable.DataSource = DataSource;
  ProductTable.Delegate = new ProductTableDelegate (DataSource);
}

Wenn die Anwendung ausgeführt wird, wird Folgendes angezeigt:

Screenshot eines Fensters mit dem Namen

Sortieren nach Spalte

Lassen Sie uns zulassen, dass der Benutzer die Daten in der Tabelle sortieren kann, indem er auf eine Spaltenüberschrift klickt. Doppelklicken Sie zuerst auf die Main.storyboard Datei, um sie zum Bearbeiten im Schnittstellen-Generator zu öffnen. Wählen Sie die Product Spalte aus, geben Title Sie für den Sortierschlüssel für die Auswahl ein, compare: und wählen Sie Ascending für die Reihenfolge aus:

Screenshot des Schnittstellen-Generators, in dem Sie den Sortierschlüssel für die Spalte

Wählen Sie die Details Spalte aus, geben Description Sie für den Sortierschlüssel für die Auswahl ein, compare: und wählen Sie Ascending für die Reihenfolge aus:

Screenshot des Schnittstellen-Generators, in dem Sie den Sortierschlüssel für die Spalte

Speichern Sie Ihre Änderungen, und kehren Sie zu Visual Studio für Mac zurück, um mit Xcode zu synchronisieren.

Jetzt bearbeiten wir die ProductTableDataSource.cs Datei und fügen die folgenden Methoden hinzu:

public void Sort(string key, bool ascending) {

  // Take action based on key
  switch (key) {
  case "Title":
    if (ascending) {
      Products.Sort ((x, y) => x.Title.CompareTo (y.Title));
    } else {
      Products.Sort ((x, y) => -1 * x.Title.CompareTo (y.Title));
    }
    break;
  case "Description":
    if (ascending) {
      Products.Sort ((x, y) => x.Description.CompareTo (y.Description));
    } else {
      Products.Sort ((x, y) => -1 * x.Description.CompareTo (y.Description));
    }
    break;
  }

}

public override void SortDescriptorsChanged (NSTableView tableView, NSSortDescriptor[] oldDescriptors)
{
  // Sort the data
  if (oldDescriptors.Length > 0) {
    // Update sort
    Sort (oldDescriptors [0].Key, oldDescriptors [0].Ascending);
  } else {
    // Grab current descriptors and update sort
    NSSortDescriptor[] tbSort = tableView.SortDescriptors;
    Sort (tbSort[0].Key, tbSort[0].Ascending);
  }

  // Refresh table
  tableView.ReloadData ();
}

Die Sort Methode ermöglicht es uns, die Daten in der Datenquelle basierend auf einem bestimmten Product Klassenfeld in aufsteigender oder absteigender Reihenfolge zu sortieren. Die überschriebene SortDescriptorsChanged Methode wird jedes Mal aufgerufen, wenn die Verwendung auf eine Spaltenüberschrift klickt. Es wird der Schlüsselwert übergeben, den wir im Schnittstellen-Generator und die Sortierreihenfolge für diese Spalte festgelegt haben.

Wenn die Anwendung ausgeführt und in die Spaltenüberschriften geklickt wird, werden die Zeilen nach dieser Spalte sortiert:

Beispiel für eine App-Ausführung

Zeilenauswahl

Wenn Sie dem Benutzer erlauben möchten, eine einzelne Zeile auszuwählen, doppelklicken Sie auf die Main.storyboard Datei, um sie zum Bearbeiten im Schnittstellen-Generator zu öffnen. Aktivieren Sie die Tabellenansicht in der Schnittstellenhierarchie , und deaktivieren Sie das Kontrollkästchen "Mehrfach " im Attributinspektor:

Screenshot des Schnittstellen-Generators, in dem Sie im Attributinspektor mehrere auswählen können.

Speichern Sie Ihre Änderungen, und kehren Sie zu Visual Studio für Mac zurück, um mit Xcode zu synchronisieren.

Bearbeiten Sie als Nächstes die ProductTableDelegate.cs Datei, und fügen Sie die folgende Methode hinzu:

public override bool ShouldSelectRow (NSTableView tableView, nint row)
{
  return true;
}

Dadurch kann der Benutzer eine beliebige einzelne Zeile in der Tabellenansicht auswählen. Geben Sie false für ShouldSelectRow jede Zeile, die der Benutzer nicht auswählen kann, oder false für jede Zeile zurück, wenn sie nicht möchten, dass der Benutzer zeilen auswählen kann.

Die Tabellenansicht (NSTableView) enthält die folgenden Methoden zum Arbeiten mit zeilenauswahl:

  • DeselectRow(nint) - Deaktiviert die angegebene Zeile in der Tabelle.
  • SelectRow(nint,bool) - Wählt die angegebene Zeile aus. Übergeben Sie false den zweiten Parameter, um jeweils nur eine Zeile auszuwählen.
  • SelectedRow - Gibt die aktuelle Zeile zurück, die in der Tabelle ausgewählt ist.
  • IsRowSelected(nint) - Gibt zurück true , wenn die angegebene Zeile ausgewählt ist.

Mehrfachzeilenauswahl

Wenn Sie dem Benutzer erlauben möchten, mehrere Zeilen auszuwählen, doppelklicken Sie auf die Main.storyboard Datei, um sie zum Bearbeiten im Schnittstellen-Generator zu öffnen. Aktivieren Sie die Tabellenansicht in der Schnittstellenhierarchie , und aktivieren Sie das Kontrollkästchen "Mehrere " im Attributinspektor:

Screenshot des Schnittstellen-Generators, in dem Sie

Speichern Sie Ihre Änderungen, und kehren Sie zu Visual Studio für Mac zurück, um mit Xcode zu synchronisieren.

Bearbeiten Sie als Nächstes die ProductTableDelegate.cs Datei, und fügen Sie die folgende Methode hinzu:

public override bool ShouldSelectRow (NSTableView tableView, nint row)
{
  return true;
}

Dadurch kann der Benutzer eine beliebige einzelne Zeile in der Tabellenansicht auswählen. Geben Sie false für ShouldSelectRow jede Zeile, die der Benutzer nicht auswählen kann, oder false für jede Zeile zurück, wenn sie nicht möchten, dass der Benutzer zeilen auswählen kann.

Die Tabellenansicht (NSTableView) enthält die folgenden Methoden zum Arbeiten mit zeilenauswahl:

  • DeselectAll(NSObject) - Deaktiviert alle Zeilen in der Tabelle. Wird this für den ersten Parameter verwendet, um das Objekt zu senden, das die Auswahl ausführt.
  • DeselectRow(nint) - Deaktiviert die angegebene Zeile in der Tabelle.
  • SelectAll(NSobject) – Wählt alle Zeilen in der Tabelle aus. Wird this für den ersten Parameter verwendet, um das Objekt zu senden, das die Auswahl ausführt.
  • SelectRow(nint,bool) - Wählt die angegebene Zeile aus. Übergeben Sie false den zweiten Parameter, und wählen Sie nur eine einzelne Zeile aus, um true die Auswahl zu erweitern und diese Zeile einzuschließen.
  • SelectRows(NSIndexSet,bool) – Wählt den angegebenen Zeilensatz aus. Übergeben Sie false den zweiten Parameter, und wählen Sie nur eine dieser Zeilen aus, um true die Auswahl zu erweitern und diese Zeilen einzuschließen.
  • SelectedRow - Gibt die aktuelle Zeile zurück, die in der Tabelle ausgewählt ist.
  • SelectedRows - Gibt einen NSIndexSet Wert zurück, der die Indizes der markierten Zeilen enthält.
  • SelectedRowCount - Gibt die Anzahl der markierten Zeilen zurück.
  • IsRowSelected(nint) - Gibt zurück true , wenn die angegebene Zeile ausgewählt ist.

Zum Auswählen der Zeile eingeben

Wenn Sie zulassen möchten, dass der Benutzer ein Zeichen mit ausgewählter Tabellenansicht eingibt und die erste Zeile mit diesem Zeichen auswählt, doppelklicken Sie auf die Main.storyboard Datei, um sie zum Bearbeiten im Schnittstellen-Generator zu öffnen. Aktivieren Sie die Tabellenansicht in der Schnittstellenhierarchie , und aktivieren Sie das Kontrollkästchen 'Typ aktivieren' im Attributinspektor:

Festlegen des Auswahltyps

Speichern Sie Ihre Änderungen, und kehren Sie zu Visual Studio für Mac zurück, um mit Xcode zu synchronisieren.

Jetzt bearbeiten wir die ProductTableDelegate.cs Datei und fügen die folgende Methode hinzu:

public override nint GetNextTypeSelectMatch (NSTableView tableView, nint startRow, nint endRow, string searchString)
{
  nint row = 0;
  foreach(Product product in DataSource.Products) {
    if (product.Title.Contains(searchString)) return row;

    // Increment row counter
    ++row;
  }

  // If not found select the first row
  return 0;
}

Die GetNextTypeSelectMatch Methode verwendet den angegebenen searchString Wert und gibt die Zeile des ersten Product zurück, der diese Zeichenfolge enthält Title.

Wenn die Anwendung ausgeführt und ein Zeichen eingegeben wird, wird eine Zeile ausgewählt:

Der Screenshot zeigt das Ergebnis der Ausführung der Anwendung.

Neuanordnen von Spalten

Wenn Sie dem Benutzer das Ziehen der Neuanordnung von Spalten in der Tabellenansicht gestatten möchten, doppelklicken Sie auf die Main.storyboard Datei, um sie zum Bearbeiten im Schnittstellen-Generator zu öffnen. Aktivieren Sie die Tabellenansicht in der Schnittstellenhierarchie , und aktivieren Sie das Kontrollkästchen "Neu anordnen " im Attributinspektor:

Screenshot des Schnittstellen-Generators, in dem Sie im Attributinspektor die Option

Wenn wir einen Wert für die Eigenschaft "Automatisches Speichern " angeben und das Feld "Spalteninformationen " überprüfen, werden alle Änderungen, die wir am Layout der Tabelle vornehmen, automatisch gespeichert und bei der nächsten Ausführung der Anwendung wiederhergestellt.

Speichern Sie Ihre Änderungen, und kehren Sie zu Visual Studio für Mac zurück, um mit Xcode zu synchronisieren.

Jetzt bearbeiten wir die ProductTableDelegate.cs Datei und fügen die folgende Methode hinzu:

public override bool ShouldReorder (NSTableView tableView, nint columnIndex, nint newColumnIndex)
{
  return true;
}

Die ShouldReorder Methode sollte für jede Spalte zurückgegeben true werden, die es zulassen soll, in die newColumnIndex, sonst zurückgegebene falseNeuanordnung gezogen werden soll;

Wenn wir die Anwendung ausführen, können wir Spaltenüberschriften verschieben, um unsere Spalten neu anzuordnen:

Ein Beispiel für die neu angeordneten Spalten

Bearbeiten von Zellen

Wenn Sie dem Benutzer erlauben möchten, die Werte für eine bestimmte Zelle zu bearbeiten, bearbeiten Sie die ProductTableDelegate.cs Datei, und ändern Sie die GetViewForItem Methode wie folgt:

public override NSView GetViewForItem (NSTableView tableView, NSTableColumn tableColumn, nint row)
{
  // This pattern allows you reuse existing views when they are no-longer in use.
  // If the returned view is null, you instance up a new view
  // If a non-null view is returned, you modify it enough to reflect the new data
  NSTextField view = (NSTextField)tableView.MakeView (tableColumn.Title, this);
  if (view == null) {
    view = new NSTextField ();
    view.Identifier = tableColumn.Title;
    view.BackgroundColor = NSColor.Clear;
    view.Bordered = false;
    view.Selectable = false;
    view.Editable = true;

    view.EditingEnded += (sender, e) => {

      // Take action based on type
      switch(view.Identifier) {
      case "Product":
        DataSource.Products [(int)view.Tag].Title = view.StringValue;
        break;
      case "Details":
        DataSource.Products [(int)view.Tag].Description = view.StringValue;
        break;
      }
    };
  }

  // Tag view
  view.Tag = row;

  // Setup view based on the column selected
  switch (tableColumn.Title) {
  case "Product":
    view.StringValue = DataSource.Products [(int)row].Title;
    break;
  case "Details":
    view.StringValue = DataSource.Products [(int)row].Description;
    break;
  }

  return view;
}

Wenn wir nun die Anwendung ausführen, kann der Benutzer die Zellen in der Tabellenansicht bearbeiten:

Beispiel zum Bearbeiten einer Zelle

Verwenden von Bildern in Tabellenansichten

Um ein Bild als Teil der Zelle in eine NSTableViewZelle einzuschließen, müssen Sie ändern, wie die Daten von der Methode der Tabellenansicht NSTableViewDelegate'sGetViewForItem zurückgegeben werden, um eine NSTableCellView anstelle der typischen NSTextFieldzu verwenden. Zum Beispiel:

public override NSView GetViewForItem (NSTableView tableView, NSTableColumn tableColumn, nint row)
{

  // This pattern allows you reuse existing views when they are no-longer in use.
  // If the returned view is null, you instance up a new view
  // If a non-null view is returned, you modify it enough to reflect the new data
  NSTableCellView view = (NSTableCellView)tableView.MakeView (tableColumn.Title, this);
  if (view == null) {
    view = new NSTableCellView ();
    if (tableColumn.Title == "Product") {
      view.ImageView = new NSImageView (new CGRect (0, 0, 16, 16));
      view.AddSubview (view.ImageView);
      view.TextField = new NSTextField (new CGRect (20, 0, 400, 16));
    } else {
      view.TextField = new NSTextField (new CGRect (0, 0, 400, 16));
    }
    view.TextField.AutoresizingMask = NSViewResizingMask.WidthSizable;
    view.AddSubview (view.TextField);
    view.Identifier = tableColumn.Title;
    view.TextField.BackgroundColor = NSColor.Clear;
    view.TextField.Bordered = false;
    view.TextField.Selectable = false;
    view.TextField.Editable = true;

    view.TextField.EditingEnded += (sender, e) => {

      // Take action based on type
      switch(view.Identifier) {
      case "Product":
        DataSource.Products [(int)view.TextField.Tag].Title = view.TextField.StringValue;
        break;
      case "Details":
        DataSource.Products [(int)view.TextField.Tag].Description = view.TextField.StringValue;
        break;
      }
    };
  }

  // Tag view
  view.TextField.Tag = row;

  // Setup view based on the column selected
  switch (tableColumn.Title) {
  case "Product":
    view.ImageView.Image = NSImage.ImageNamed ("tags.png");
    view.TextField.StringValue = DataSource.Products [(int)row].Title;
    break;
  case "Details":
    view.TextField.StringValue = DataSource.Products [(int)row].Description;
    break;
  }

  return view;
}

Weitere Informationen finden Sie im Abschnitt "Verwenden von Bildern mit Tabellenansichten " in unserer Dokumentation zum Arbeiten mit Bildern .

Hinzufügen einer Schaltfläche "Löschen" zu einer Zeile

Basierend auf den Anforderungen Ihrer App kann es vorkommen, dass Sie eine Interaktive Schaltfläche für jede Zeile in der Tabelle angeben müssen. Als Beispiel hierfür erweitern wir das oben erstellte Tabellenansichtsbeispiel, um eine Schaltfläche "Löschen " in jede Zeile einzuschließen.

Bearbeiten Sie zuerst den Main.storyboard Schnittstellen-Generator von Xcode, wählen Sie die Tabellenansicht aus, und erhöhen Sie die Anzahl der Spalten auf drei (3). Ändern Sie als Nächstes den Titel der neuen Spalte in Action:

Bearbeiten des Spaltennamens

Speichern Sie die Änderungen im Storyboard, und kehren Sie zu Visual Studio für Mac zurück, um die Änderungen zu synchronisieren.

Bearbeiten Sie als Nächstes die ViewController.cs Datei, und fügen Sie die folgende öffentliche Methode hinzu:

public void ReloadTable ()
{
  ProductTable.ReloadData ();
}

Ändern Sie in derselben Datei die Erstellung des neuen Tabellenansichtsdelegats innerhalb der ViewDidLoad Methode wie folgt:

// Populate the Product Table
ProductTable.DataSource = DataSource;
ProductTable.Delegate = new ProductTableDelegate (this, DataSource);

Bearbeiten Sie nun die ProductTableDelegate.cs Datei so, dass sie eine private Verbindung mit dem Ansichtscontroller enthält, und verwenden Sie den Controller als Parameter beim Erstellen einer neuen Instanz des Delegaten:

#region Private Variables
private ProductTableDataSource DataSource;
private ViewController Controller;
#endregion

#region Constructors
public ProductTableDelegate (ViewController controller, ProductTableDataSource datasource)
{
  this.Controller = controller;
  this.DataSource = datasource;
}
#endregion

Fügen Sie als Nächstes der Klasse die folgende neue private Methode hinzu:

private void ConfigureTextField (NSTableCellView view, nint row)
{
  // Add to view
  view.TextField.AutoresizingMask = NSViewResizingMask.WidthSizable;
  view.AddSubview (view.TextField);

  // Configure
  view.TextField.BackgroundColor = NSColor.Clear;
  view.TextField.Bordered = false;
  view.TextField.Selectable = false;
  view.TextField.Editable = true;

  // Wireup events
  view.TextField.EditingEnded += (sender, e) => {

    // Take action based on type
    switch (view.Identifier) {
    case "Product":
      DataSource.Products [(int)view.TextField.Tag].Title = view.TextField.StringValue;
      break;
    case "Details":
      DataSource.Products [(int)view.TextField.Tag].Description = view.TextField.StringValue;
      break;
    }
  };

  // Tag view
  view.TextField.Tag = row;
}

Dadurch werden alle Textansichtskonfigurationen verwendet, die zuvor in der GetViewForItem Methode ausgeführt wurden, und platziert sie an einer einzigen aufrufbaren Position (da die letzte Spalte der Tabelle keine Textansicht, sondern eine Schaltfläche enthält).

Bearbeiten Sie schließlich die GetViewForItem Methode, und lassen Sie sie wie folgt aussehen:

public override NSView GetViewForItem (NSTableView tableView, NSTableColumn tableColumn, nint row)
{

  // This pattern allows you reuse existing views when they are no-longer in use.
  // If the returned view is null, you instance up a new view
  // If a non-null view is returned, you modify it enough to reflect the new data
  NSTableCellView view = (NSTableCellView)tableView.MakeView (tableColumn.Title, this);
  if (view == null) {
    view = new NSTableCellView ();

    // Configure the view
    view.Identifier = tableColumn.Title;

    // Take action based on title
    switch (tableColumn.Title) {
    case "Product":
      view.ImageView = new NSImageView (new CGRect (0, 0, 16, 16));
      view.AddSubview (view.ImageView);
      view.TextField = new NSTextField (new CGRect (20, 0, 400, 16));
      ConfigureTextField (view, row);
      break;
    case "Details":
      view.TextField = new NSTextField (new CGRect (0, 0, 400, 16));
      ConfigureTextField (view, row);
      break;
    case "Action":
      // Create new button
      var button = new NSButton (new CGRect (0, 0, 81, 16));
      button.SetButtonType (NSButtonType.MomentaryPushIn);
      button.Title = "Delete";
      button.Tag = row;

      // Wireup events
      button.Activated += (sender, e) => {
        // Get button and product
        var btn = sender as NSButton;
        var product = DataSource.Products [(int)btn.Tag];

        // Configure alert
        var alert = new NSAlert () {
          AlertStyle = NSAlertStyle.Informational,
          InformativeText = $"Are you sure you want to delete {product.Title}? This operation cannot be undone.",
          MessageText = $"Delete {product.Title}?",
        };
        alert.AddButton ("Cancel");
        alert.AddButton ("Delete");
        alert.BeginSheetForResponse (Controller.View.Window, (result) => {
          // Should we delete the requested row?
          if (result == 1001) {
            // Remove the given row from the dataset
            DataSource.Products.RemoveAt((int)btn.Tag);
            Controller.ReloadTable ();
          }
        });
      };

      // Add to view
      view.AddSubview (button);
      break;
    }

  }

  // Setup view based on the column selected
  switch (tableColumn.Title) {
  case "Product":
    view.ImageView.Image = NSImage.ImageNamed ("tag.png");
    view.TextField.StringValue = DataSource.Products [(int)row].Title;
    view.TextField.Tag = row;
    break;
  case "Details":
    view.TextField.StringValue = DataSource.Products [(int)row].Description;
    view.TextField.Tag = row;
    break;
  case "Action":
    foreach (NSView subview in view.Subviews) {
      var btn = subview as NSButton;
      if (btn != null) {
        btn.Tag = row;
      }
    }
    break;
  }

  return view;
}

Sehen wir uns einige Abschnitte dieses Codes ausführlicher an. Wenn eine neue NSTableViewCell Aktion erstellt wird, wird zunächst basierend auf dem Namen der Spalte ausgeführt. Für die ersten beiden Spalten (Produkt und Details) wird die neue ConfigureTextField Methode aufgerufen.

Für die Spalte "Aktion " wird eine neue NSButton erstellt und der Zelle als Unteransicht hinzugefügt:

// Create new button
var button = new NSButton (new CGRect (0, 0, 81, 16));
button.SetButtonType (NSButtonType.MomentaryPushIn);
button.Title = "Delete";
button.Tag = row;
...

// Add to view
view.AddSubview (button);

Die Eigenschaft der Schaltfläche Tag wird verwendet, um die Nummer der Zeile zu halten, die derzeit verarbeitet wird. Diese Nummer wird später verwendet, wenn der Benutzer eine Zeile anfordert, im Ereignis der Schaltfläche Activated gelöscht zu werden:

// Wireup events
button.Activated += (sender, e) => {
  // Get button and product
  var btn = sender as NSButton;
  var product = DataSource.Products [(int)btn.Tag];

  // Configure alert
  var alert = new NSAlert () {
    AlertStyle = NSAlertStyle.Informational,
    InformativeText = $"Are you sure you want to delete {product.Title}? This operation cannot be undone.",
    MessageText = $"Delete {product.Title}?",
  };
  alert.AddButton ("Cancel");
  alert.AddButton ("Delete");
  alert.BeginSheetForResponse (Controller.View.Window, (result) => {
    // Should we delete the requested row?
    if (result == 1001) {
      // Remove the given row from the dataset
      DataSource.Products.RemoveAt((int)btn.Tag);
      Controller.ReloadTable ();
    }
  });
};

Am Anfang des Ereignishandlers rufen wir die Schaltfläche und das Produkt ab, das sich in der angegebenen Tabellenzeile befindet. Anschließend wird dem Benutzer eine Warnung angezeigt, die das Löschen der Zeile bestätigt. Wenn der Benutzer die Zeile löscht, wird die angegebene Zeile aus der Datenquelle entfernt, und die Tabelle wird neu geladen:

// Remove the given row from the dataset
DataSource.Products.RemoveAt((int)btn.Tag);
Controller.ReloadTable ();

Wenn die Tabellenansichtszelle nicht neu erstellt wird, sondern wiederverwendet wird, konfiguriert der folgende Code sie basierend auf der verarbeiteten Spalte:

// Setup view based on the column selected
switch (tableColumn.Title) {
case "Product":
  view.ImageView.Image = NSImage.ImageNamed ("tag.png");
  view.TextField.StringValue = DataSource.Products [(int)row].Title;
  view.TextField.Tag = row;
  break;
case "Details":
  view.TextField.StringValue = DataSource.Products [(int)row].Description;
  view.TextField.Tag = row;
  break;
case "Action":
  foreach (NSView subview in view.Subviews) {
    var btn = subview as NSButton;
    if (btn != null) {
      btn.Tag = row;
    }
  }
  break;
}

Für die Spalte "Aktion " werden alle Unteransichten gescannt, bis sie NSButton gefunden werden, und dann wird sie Tag aktualisiert, um auf die aktuelle Zeile zu zeigen.

Wenn die App ausgeführt wird, werden diese Änderungen vorgenommen, wenn jede Zeile ausgeführt wird, über eine Schaltfläche "Löschen ":

Die Tabellenansicht mit Löschschaltflächen

Wenn der Benutzer auf eine Schaltfläche "Löschen " klickt, wird eine Benachrichtigung angezeigt, in der er aufgefordert wird, die angegebene Zeile zu löschen:

Warnung zur Löschzeile

Wenn der Benutzer "Löschen" auswäht, wird die Zeile entfernt, und die Tabelle wird neu gezeichnet:

Die Tabelle nach dem Löschen der Zeile

Datenbindungstabellenansichten

Mithilfe von Key-Value Coding- und Datenbindungstechniken in Ihrer Xamarin.Mac-Anwendung können Sie die Menge an Code, den Sie schreiben müssen, erheblich verringern und Standard, um UI-Elemente aufzufüllen und zu arbeiten. Außerdem profitieren Sie von der weiteren Entkoppelung Ihrer Sicherungsdaten (Datenmodell) von der Front-End-Benutzeroberfläche (Model-View-Controller), was zu einfacheren Standard nachhaltigen, flexibleren Anwendungsdesigns führt.

Key-Value Coding (KVC) ist ein Mechanismus für den indirekten Zugriff auf die Eigenschaften eines Objekts mithilfe von Schlüsseln (speziell formatierte Zeichenfolgen), um Eigenschaften zu identifizieren, anstatt über Instanzvariablen oder Accessormethoden (get/set) darauf zuzugreifen. Durch die Implementierung von Key-Value Coding-kompatiblen Accessoren in Ihrer Xamarin.Mac-Anwendung erhalten Sie Zugriff auf andere macOS-Features wie Key-Value Observing (KVO), Datenbindung, Core Data, Cocoa-Bindungen und Skriptierbarkeit.

Weitere Informationen finden Sie im Abschnitt "Datenbindung in der Tabellenansicht" unserer Dokumentation "Datenbindung" und "Key-Value Coding" .

Zusammenfassung

Dieser Artikel hat einen detaillierten Blick auf die Arbeit mit Tabellenansichten in einer Xamarin.Mac-Anwendung genommen. Wir haben die verschiedenen Typen und Verwendungen von Tabellenansichten gesehen, wie Tabellenansichten im Schnittstellen-Generator von Xcode erstellt und Standard enthalten sind und wie Sie mit Tabellenansichten in C#-Code arbeiten.