Gliederungsansichten in Xamarin.Mac

In diesem Artikel wird das Arbeiten mit Gliederungsansichten in einer Xamarin.Mac-Anwendung behandelt. Es beschreibt das Erstellen und Verwalten von Gliederungsansichten in Xcode und Interface Builder sowie das programmgesteuerte Arbeiten mit ihnen.

Wenn Sie mit C# und .NET in einer Xamarin.Mac-Anwendung arbeiten, haben Sie Zugriff auf die gleichen Gliederungsansichten wie ein Entwickler, der in Objective-C und Xcode arbeitet. Da Xamarin.Mac direkt in Xcode integriert wird, können Sie den Schnittstellen-Generator von Xcode verwenden, um Ihre Gliederungsansichten zu erstellen und zu verwalten (oder sie optional direkt in C#-Code zu erstellen).

Eine Gliederungsansicht ist ein Typ von Table, der es dem Benutzer ermöglicht, Zeilen hierarchischer Daten zu erweitern oder zu reduzieren. Wie in einer Tabellenansicht zeigt eine Gliederungsansicht Daten für einen Satz verwandter Elemente an, wobei Zeilen einzelne Elemente und Spalten die Attribute dieser Elemente darstellen. Im Gegensatz zu einer Tabellenansicht befinden sich Elemente in einer Gliederungsansicht nicht in einer flachen Liste, sie sind in einer Hierarchie organisiert, z. B. Dateien und Ordner auf einer Festplatte.

Beispiel für eine App-Ausführung

In diesem Artikel werden die Grundlagen der Arbeit mit Gliederungsansichten in einer Xamarin.Mac-Anwendung behandelt. 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 Aktionen , da er wichtige Konzepte und Techniken behandelt, die wir in diesem Artikel verwenden werden.

Möglicherweise sollten Sie auch einen Blick auf den Abschnitt Verfügbarmachen von C#-Klassen/-Methoden für Objective-C das Xamarin.Mac Internals-Dokument werfen. Darin werden die Befehle und Export erläutert, die Register zum Verknüpfen Ihrer C#-Klassen mit Objective-C Objekten und UI-Elementen verwendet werden.

Einführung in Gliederungsansichten

Eine Gliederungsansicht ist ein Typ von Table, der es dem Benutzer ermöglicht, Zeilen hierarchischer Daten zu erweitern oder zu reduzieren. Wie in einer Tabellenansicht zeigt eine Gliederungsansicht Daten für einen Satz verwandter Elemente an, wobei Zeilen einzelne Elemente und Spalten die Attribute dieser Elemente darstellen. Im Gegensatz zu einer Tabellenansicht befinden sich Elemente in einer Gliederungsansicht nicht in einer flachen Liste, sie sind in einer Hierarchie organisiert, z. B. Dateien und Ordner auf einer Festplatte.

Wenn ein Element in einer Gliederungsansicht andere Elemente enthält, kann es vom Benutzer erweitert oder reduziert werden. Ein erweiterbares Element zeigt ein Offenlegungsdreieck an, das nach rechts zeigt, wenn das Element reduziert wird, und nach unten zeigt, wenn das Element erweitert wird. Wenn Sie auf das Offenlegungsdreieck klicken, wird das Element erweitert oder reduziert.

Die Gliederungsansicht (NSOutlineView) ist eine Unterklasse der Tabellenansicht (NSTableView) und erbt daher einen Großteil ihres Verhaltens von ihrer übergeordneten Klasse. Daher werden viele Vorgänge, die von einer Tabellenansicht unterstützt werden, z. B. das Auswählen von Zeilen oder Spalten, das Neupositionieren von Spalten durch Ziehen von Spaltenüberschriften usw., auch von einer Gliederungsansicht unterstützt. Eine Xamarin.Mac-Anwendung hat die Kontrolle über diese Features und kann die Parameter der Gliederungsansicht (entweder im Code oder im Schnittstellen-Generator) konfigurieren, um bestimmte Vorgänge zuzulassen oder zu verbieten.

Eine Gliederungsansicht speichert keine eigenen Daten, sondern basiert auf einer Datenquelle (NSOutlineViewDataSource), um sowohl die erforderlichen Zeilen als auch Spalten nach Bedarf bereitzustellen.

Das Verhalten einer Gliederungsansicht kann angepasst werden, indem eine Unterklasse des Gliederungsansichtsdelegaten (NSOutlineViewDelegate) bereitgestellt wird, um die Verwaltung von Gliederungsspalten zu unterstützen, den Typ zum Auswählen von Funktionen, Zeilenauswahl und -bearbeitung, benutzerdefinierte Nachverfolgung und benutzerdefinierte Ansichten für einzelne Spalten und Zeilen bereitzustellen.

Da eine Gliederungsansicht einen Großteil ihres Verhaltens und ihrer Funktionalität mit einer Tabellenansicht teilt, sollten Sie die Dokumentation zu Tabellenansichten durchgehen, bevor Sie mit diesem Artikel fortfahren.

Erstellen und Verwalten von Gliederungsansichten in Xcode

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

Auswählen des Standard Storyboards

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

Bearbeiten der Benutzeroberfläche in Xcode

Geben Sie outline in das Suchfeld des Bibliotheksinspektors ein, um das Auffinden der Gliederungsansicht-Steuerelemente zu erleichtern:

Auswählen einer Gliederungsansicht aus der Bibliothek

Ziehen Sie eine Gliederungsansicht auf den Ansichtscontroller im Schnittstellen-Editor, füllen Sie ihn den Inhaltsbereich des Ansichtscontrollers aus, und legen Sie ihn dort fest, wo sie verkleinern und mit dem Fenster im Einschränkungs-Editor vergrößert wird:

Bearbeiten der Einschränkungen

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

Screenshot: Verfügbare Eigenschaften im Attributinspektor

  • Gliederungsspalte : Die Tabellenspalte, in der die hierarchischen Daten angezeigt werden.
  • Automatisches Speichern der Gliederungsspalte : Wenn true, wird die Gliederungsspalte automatisch zwischen Anwendungsausführungen gespeichert und wiederhergestellt.
  • Einzug : Der Betrag, der Spalten unter einem erweiterten Element eingezogen werden soll.
  • Einzug folgt Zellen : Wenn true, wird das Einzugszeichen zusammen mit den Zellen eingezogen.
  • Automatisches Speichern erweiterter Elemente : Wenn truefestgelegt ist, wird der erweiterte/reduzierte Zustand der Elemente automatisch zwischen Anwendungsausführungen gespeichert und wiederhergestellt.
  • Inhaltsmodus : Ermöglicht die Verwendung von Ansichten (NSView) oder Zellen (NSCell), um die Daten in den Zeilen und Spalten anzuzeigen. Ab macOS 10.7 sollten Sie Ansichten verwenden.
  • Gleitkommagruppenzeilen : Wenn true, zeichnet die Tabellenansicht gruppierte Zellen so, als ob sie schweben.
  • Spalten : Definiert die Anzahl der angezeigten Spalten.
  • Header: Wenn true, verfügen die Spalten über Header.
  • Neuanordnung : Wenn true, kann der Benutzer die Spalten in der Tabelle neu anordnen.
  • Ändern der Größe : Wenn true, kann der Benutzer Spaltenüberschriften ziehen, um die Spaltengröße zu ändern.
  • Spaltengröße: Steuert die automatische Größe von Spalten in der Tabelle.
  • Hervorhebung : Steuert den Typ der Hervorhebung, die die Tabelle verwendet, wenn eine Zelle ausgewählt wird.
  • Alternative Zeilen : Wenn true, weist eine andere Zeile eine andere Hintergrundfarbe auf.
  • Horizontales Raster : Wählt den Typ des Rahmens aus, der horizontal zwischen Zellen 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 wie folgt auswählen kann:
    • Mehrfach : Wenn true, kann der Benutzer mehrere Zeilen und Spalten auswählen.
    • Spalte : Wenn true, kann der Benutzer Spalten auswählen.
    • Geben Sie Auswählen ein: Wenn true, kann der Benutzer ein Zeichen eingeben, um eine Zeile auszuwählen.
    • Leer : Wenn trueder Benutzer keine Zeile oder Spalte auswählen muss, lässt die Tabelle überhaupt keine Auswahl zu.
  • Automatische Speicherung : Der Name, unter dem das Tabellenformat automatisch gespeichert wird.
  • Spalteninformationen : Wenn true, werden die Reihenfolge und Breite der Spalten automatisch gespeichert.
  • Zeilenumbrüche : Wählen Sie aus, wie die Zelle Zeilenumbrüche behandelt.
  • Schneidet die letzte sichtbare Zeile ab: Wenn truedie Zelle in den Daten abgeschnitten wird, kann nicht in ihre Grenzen passen.

Wichtig

Es sei denn, Sie verwalten eine ältere Xamarin.Mac-Anwendung, NSView sollten basierende Gliederungsansichten über basierende NSCell Tabellenansichten verwendet werden. NSCell gilt als legacy und wird möglicherweise in Zukunft nicht mehr unterstützt.

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

Screenshot: Verfügbare Eigenschaften für die ausgewählte Tabellenspalte im Attributinspektor

  • Titel : Legt den Titel der Spalte fest.
  • Ausrichtung : Legt die Ausrichtung des Texts innerhalb der Zellen fest.
  • Titelschriftart : Wählt die Schriftart für den Headertext der Zelle aus.
  • Sortierschlüssel : Der Schlüssel, der zum Sortieren von Daten in der Spalte verwendet wird. Lassen Sie leer, wenn der Benutzer diese Spalte nicht sortieren kann.
  • Selektor : Die Aktion , die zum Ausführen der Sortierung verwendet wird. Lassen Sie leer, wenn der Benutzer diese Spalte nicht sortieren kann.
  • Reihenfolge : 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 die Größe der Spalte auch ändern, indem Sie den Ziehpunkt (vertikal zentriert auf der rechten Seite der Spalte) nach links oder rechts ziehen.

Wählen Sie die einzelnen Spalten in der Tabellenansicht aus, und weisen Sie der ersten Spalte den Titel und Product die zweite spalte zu Details.

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

Screenshot: Verfügbare Eigenschaften für die ausgewählte Tabellenzelle im Attributinspektor

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: Verfügbare Eigenschaften für die ausgewählte Tabellenansichtszelle im Attributinspektor

Hier müssen alle Eigenschaften eines Standardtextfelds festgelegt werden. 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:

Screenshot: Verfügbare Eigenschaften für die ausgewählte Tabellenansichtszelle

Die wichtigsten Einstellungen sind hier:

  • Layout : Wählen Sie aus, wie Zellen in dieser Spalte angeordnet werden.
  • Verwendet den Einzelzeilenmodus : Wenn true, ist die Zelle auf eine einzelne Zeile beschränkt.
  • Breite des ersten Laufzeitlayouts : Wenn true, bevorzugt die Zelle die für sie festgelegte Breite (entweder manuell oder automatisch), wenn sie bei der ersten Ausführung der Anwendung angezeigt wird.
  • Aktion : Steuert, wann 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 : Wenn true, übernimmt die Zelle die Verantwortung für das Rückgängig-Verhalten.

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

Auswählen der Tabellenzellenansicht

Dadurch 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 Outlets

Genau wie jedes andere Cocoa UI-Steuerelement müssen wir unsere Gliederungsansicht und ihre Spalten und Zellen für C#-Code mit Aktionen und Outlets verfügbar machen (basierend auf der erforderlichen Funktionalität).

Der Prozess ist für jedes Gliederungsansichtselement identisch, das wir verfügbar machen möchten:

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

    Auswählen der richtigen H-Datei

  2. Wählen Sie in der Schnittstellenhierarchie die Gliederungsansicht aus, klicken Sie bei gedrückter Ctrl-Taste, und ziehen Sie sie in die ViewController.h Datei.

  3. Erstellen Sie eine Steckdose für die Gliederungsansicht mit dem Namen ProductOutline:

    Screenshot: Outlet mit dem Namen ProductOutline im Attributinspektor

  4. Erstellen Sie Outlets für die Tabellenspalten mit dem Namen ProductColumn und DetailsColumn:

    Screenshot: Outlet mit dem Namen DetailsColumn im Attributinspektor

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

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

Auffüllen der Gliederungsansicht

Mit unserer Gliederungsansicht, die im Schnittstellen-Generator entworfen und über ein Outlet verfügbar gemacht wurde, müssen wir als Nächstes den C#-Code erstellen, um ihn aufzufüllen.

Zunächst erstellen wir eine neue Product Klasse, die die Informationen für die einzelnen Zeilen und Gruppen von Unterprodukten enthält. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt, und wählen SieNeue Dateihinzufügen>... aus. Wählen Sie Allgemein>Leere Klasse aus, geben Sie Product als Name ein, und klicken Sie auf die Schaltfläche Neu:

Erstellen einer leeren Klasse

Lassen Sie die Product.cs Datei wie folgt aussehen:

using System;
using Foundation;
using System.Collections.Generic;

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

        #region Computed Properties
        public string Title { get; set;} = "";
        public string Description { get; set;} = "";
        public bool IsProductGroup {
            get { return (Products.Count > 0); }
        }
        #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 von NSOutlineDataSource erstellen, um die Daten für unsere Gliederung bereitzustellen, während sie angefordert wird. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt, und wählen SieNeue Dateihinzufügen>... aus. Wählen Sie Allgemein>Leere Klasse aus, geben Sie ProductOutlineDataSource als Name ein, und klicken Sie auf die Schaltfläche Neu.

Bearbeiten Sie die ProductTableDataSource.cs Datei, und lassen Sie sie wie folgt aussehen:

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

namespace MacOutlines
{
    public class ProductOutlineDataSource : NSOutlineViewDataSource
    {
        #region Public Variables
        public List<Product> Products = new List<Product>();
        #endregion

        #region Constructors
        public ProductOutlineDataSource ()
        {
        }
        #endregion

        #region Override Methods
        public override nint GetChildrenCount (NSOutlineView outlineView, NSObject item)
        {
            if (item == null) {
                return Products.Count;
            } else {
                return ((Product)item).Products.Count;
            }

        }

        public override NSObject GetChild (NSOutlineView outlineView, nint childIndex, NSObject item)
        {
            if (item == null) {
                return Products [childIndex];
            } else {
                return ((Product)item).Products [childIndex];
            }

        }

        public override bool ItemExpandable (NSOutlineView outlineView, NSObject item)
        {
            if (item == null) {
                return Products [0].IsProductGroup;
            } else {
                return ((Product)item).IsProductGroup;
            }

        }
        #endregion
    }
}

Diese Klasse verfügt über Speicher für die Elemente der Gliederungsansicht und überschreibt die GetChildrenCount , um die Anzahl der Zeilen in der Tabelle zurückzugeben. Gibt GetChild ein bestimmtes übergeordnetes oder untergeordnetes Element zurück (wie von der Gliederungsansicht angefordert), und definiert ItemExpandable das angegebene Element entweder als übergeordnetes oder untergeordnetes Element.

Schließlich müssen wir eine Unterklasse von NSOutlineDelegate erstellen, um das Verhalten für unsere Gliederung bereitzustellen. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt, und wählen SieNeue Dateihinzufügen>... aus. Wählen Sie Allgemein>Leere Klasse aus, geben Sie ProductOutlineDelegate als Name ein, und klicken Sie auf die Schaltfläche Neu.

Bearbeiten Sie die ProductOutlineDelegate.cs Datei, und lassen Sie sie wie folgt aussehen:

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

namespace MacOutlines
{
    public class ProductOutlineDelegate : NSOutlineViewDelegate
    {
        #region Constants
        private const string CellIdentifier = "ProdCell";
        #endregion

        #region Private Variables
        private ProductOutlineDataSource DataSource;
        #endregion

        #region Constructors
        public ProductOutlineDelegate (ProductOutlineDataSource datasource)
        {
            this.DataSource = datasource;
        }
        #endregion

        #region Override Methods

        public override NSView GetView (NSOutlineView outlineView, NSTableColumn tableColumn, NSObject item) {
            // 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)outlineView.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;
            }

            // Cast item
            var product = item as Product;

            // Setup view based on the column selected
            switch (tableColumn.Title) {
            case "Product":
                view.StringValue = product.Title;
                break;
            case "Details":
                view.StringValue = product.Description;
                break;
            }

            return view;
        }
        #endregion
    }
}

Wenn wir eine instance von ProductOutlineDelegateerstellen, übergeben wir auch eine instance der, die ProductOutlineDataSource die Daten für die Gliederung bereitstellt. Die GetView -Methode ist dafür verantwortlich, eine Ansicht (Daten) zurückzugeben, um die Zelle für eine geben-Spalte und -Zeile anzuzeigen. Wenn möglich, wird eine vorhandene Ansicht wiederverwendet, um die Zelle anzuzeigen. Andernfalls muss eine neue Ansicht erstellt werden.

Um die Gliederung aufzufüllen, bearbeiten wir die MainWindow.cs Datei, und lassen Sie die AwakeFromNib Methode wie folgt aussehen:

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

    // Create data source and populate
    var DataSource = new ProductOutlineDataSource ();

    var Vegetables = new Product ("Vegetables", "Greens and Other Produce");
    Vegetables.Products.Add (new Product ("Cabbage", "Brassica oleracea - Leaves, axillary buds, stems, flowerheads"));
    Vegetables.Products.Add (new Product ("Turnip", "Brassica rapa - Tubers, leaves"));
    Vegetables.Products.Add (new Product ("Radish", "Raphanus sativus - Roots, leaves, seed pods, seed oil, sprouting"));
    Vegetables.Products.Add (new Product ("Carrot", "Daucus carota - Root tubers"));
    DataSource.Products.Add (Vegetables);

    var Fruits = new Product ("Fruits", "Fruit is a part of a flowering plant that derives from specific tissues of the flower");
    Fruits.Products.Add (new Product ("Grape", "True Berry"));
    Fruits.Products.Add (new Product ("Cucumber", "Pepo"));
    Fruits.Products.Add (new Product ("Orange", "Hesperidium"));
    Fruits.Products.Add (new Product ("Blackberry", "Aggregate fruit"));
    DataSource.Products.Add (Fruits);

    var Meats = new Product ("Meats", "Lean Cuts");
    Meats.Products.Add (new Product ("Beef", "Cow"));
    Meats.Products.Add (new Product ("Pork", "Pig"));
    Meats.Products.Add (new Product ("Veal", "Young Cow"));
    DataSource.Products.Add (Meats);

    // Populate the outline
    ProductOutline.DataSource = DataSource;
    ProductOutline.Delegate = new ProductOutlineDelegate (DataSource);

}

Wenn wir die Anwendung ausführen, wird Folgendes angezeigt:

Die reduzierte Ansicht

Wenn wir einen Knoten in der Gliederungsansicht erweitern, sieht er wie folgt aus:

Die erweiterte Ansicht

Sortieren nach Spalte

Lassen Sie es dem Benutzer ermöglichen, die Daten in der Gliederung zu sortieren, indem er auf eine Spaltenüberschrift klickt. Doppelklicken Sie zunächst auf die Main.storyboard Datei, um sie zur Bearbeitung in Interface Builder zu öffnen. Wählen Sie die Product Spalte aus, geben Sie Title für den Sortierschlüssel für die Auswahl ein, compare: und wählen Sie Ascending für Die Bestellung aus:

Festlegen der Sortierschlüsselreihenfolge

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

Nun bearbeiten wir die ProductOutlineDataSource.cs Datei, und fügen Sie 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;
    }
}

public override void SortDescriptorsChanged (NSOutlineView outlineView, NSSortDescriptor[] oldDescriptors)
{
    // Sort the data
    Sort (oldDescriptors [0].Key, oldDescriptors [0].Ascending);
    outlineView.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 bei jeder Verwendung von Klicks auf eine Spaltenüberschrift aufgerufen. Es wird der Schlüsselwert übergeben, den wir im Schnittstellen-Generator festgelegt haben, und die Sortierreihenfolge für diese Spalte.

Wenn wir die Anwendung ausführen und auf die Spaltenüberschriften klicken, werden die Zeilen nach dieser Spalte sortiert:

Beispiel für sortierte Ausgabe

Zeilenauswahl

Wenn Sie dem Benutzer erlauben möchten, eine einzelne Zeile auszuwählen, doppelklicken Sie auf die Main.storyboard Datei, um sie zur Bearbeitung in Interface Builder zu öffnen. Aktivieren Sie die Gliederungsansicht in der Schnittstellenhierarchie , und deaktivieren Sie das Kontrollkästchen Mehrere im Attributinspektor:

Screenshot: Attributinspektor, in dem Sie die Einstellung

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

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

public override bool ShouldSelectItem (NSOutlineView outlineView, NSObject item)
{
    // Don't select product groups
    return !((Product)item).IsProductGroup;
}

Dadurch kann der Benutzer eine beliebige einzelne Zeile in der Gliederungsansicht auswählen. Geben Sie false für ShouldSelectItem jedes Element zurück, das der Benutzer nicht auswählen kann, oder false für jedes Element, wenn sie nicht möchten, dass der Benutzer Elemente auswählen kann.

Auswahl mehrerer Zeilen

Wenn Sie dem Benutzer erlauben möchten, mehrere Zeilen auszuwählen, doppelklicken Sie auf die Main.storyboard Datei, um sie zur Bearbeitung in Interface Builder zu öffnen. Aktivieren Sie die Gliederungsansicht in der Schnittstellenhierarchie , und aktivieren Sie das Kontrollkästchen Mehrere im Attributinspektor:

Screenshot: Attributinspektor, in dem Sie Mehrere auswählen können

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

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

public override bool ShouldSelectItem (NSOutlineView outlineView, NSObject item)
{
    // Don't select product groups
    return !((Product)item).IsProductGroup;
}

Dadurch kann der Benutzer eine beliebige einzelne Zeile in der Gliederungsansicht auswählen. Geben Sie false für ShouldSelectRow jedes Element zurück, das der Benutzer nicht auswählen kann, oder false für jedes Element, wenn sie nicht möchten, dass der Benutzer Elemente auswählen kann.

Typ zum Auswählen der Zeile

Wenn Sie dem Benutzer erlauben möchten, ein Zeichen mit ausgewählter Gliederungsansicht einzugeben und die erste Zeile auszuwählen, die dieses Zeichen enthält, doppelklicken Sie auf die Main.storyboard Datei, um es zur Bearbeitung im Schnittstellen-Generator zu öffnen. Wählen Sie die Gliederungsansicht in der Schnittstellenhierarchie aus , und aktivieren Sie das Kontrollkästchen Typauswahl im Attributinspektor:

Bearbeiten des Zeilentyps

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

Nun bearbeiten wir die ProductOutlineDelegate.cs Datei und fügen die folgende Methode hinzu:

public override NSObject GetNextTypeSelectMatch (NSOutlineView outlineView, NSObject startItem, NSObject endItem, string searchString)
{
    foreach(Product product in DataSource.Products) {
        if (product.Title.Contains (searchString)) {
            return product;
        }
    }

    // Not found
    return null;
}

Die GetNextTypeSelectMatch -Methode akzeptiert das angegebene searchString und gibt das Element der ersten Product zurück, in der diese Zeichenfolge enthalten ist Title.

Neuanordnen von Spalten

Wenn Sie dem Benutzer das Ziehen von Neuanordnungsspalten in der Gliederungsansicht ermöglichen möchten, doppelklicken Sie auf die Main.storyboard Datei, um sie zur Bearbeitung im Schnittstellen-Generator zu öffnen. Wählen Sie die Gliederungsansicht in der Schnittstellenhierarchie aus , und aktivieren Sie das Kontrollkästchen Neuanordnung im Attributinspektor:

Screenshot: Attributinspektor, in dem Sie neu anordnen auswählen können

Wenn wir einen Wert für die Autoave-Eigenschaft angeben und das Feld Spalteninformationen überprüfen, werden alle Änderungen, die wir am Tabellenlayout vornehmen, automatisch für uns 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 sie mit Xcode zu synchronisieren.

Nun bearbeiten wir die ProductOutlineDelegate.cs Datei und fügen die folgende Methode hinzu:

public override bool ShouldReorder (NSOutlineView outlineView, nint columnIndex, nint newColumnIndex)
{
    return true;
}

Die ShouldReorder -Methode sollte für jede Spalte zurückgeben true , die sie zulassen möchte, dass sie in die newColumnIndex-Spalte umsortiert werden soll, andernfalls zurückgeben false.

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

Beispiel für das Neuanordnen von Spalten

Bearbeiten von Zellen

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

public override NSView GetView (NSOutlineView outlineView, NSTableColumn tableColumn, NSObject item) {
    // Cast item
    var product = item as Product;

    // 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)outlineView.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 = !product.IsProductGroup;
    }

    // Tag view
    view.Tag = outlineView.RowForItem (item);

    // Allow for edit
    view.EditingEnded += (sender, e) => {

        // Grab product
        var prod = outlineView.ItemAtRow(view.Tag) as Product;

        // Take action based on type
        switch(view.Identifier) {
        case "Product":
            prod.Title = view.StringValue;
            break;
        case "Details":
            prod.Description = view.StringValue;
            break;
        }
    };

    // Setup view based on the column selected
    switch (tableColumn.Title) {
    case "Product":
        view.StringValue = product.Title;
        break;
    case "Details":
        view.StringValue = product.Description;
        break;
    }

    return view;
}

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

Ein Beispiel für die Bearbeitung von Zellen

Verwenden von Bildern in Gliederungsansichten

Um ein Bild als Teil der Zelle in ein NSOutlineVieweinzuschließen, müssen Sie ändern, wie die Daten von der Methode der GliederungsansichtGetViewNSTableViewDelegate'szurückgegeben werden, um anstelle NSTableCellView der typischen NSTextFieldzu verwenden. Beispiel:

public override NSView GetView (NSOutlineView outlineView, NSTableColumn tableColumn, NSObject item) {
    // Cast item
    var product = item as Product;

    // 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)outlineView.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 = !product.IsProductGroup;
    }

    // Tag view
    view.TextField.Tag = outlineView.RowForItem (item);

    // Allow for edit
    view.TextField.EditingEnded += (sender, e) => {

        // Grab product
        var prod = outlineView.ItemAtRow(view.Tag) as Product;

        // Take action based on type
        switch(view.Identifier) {
        case "Product":
            prod.Title = view.TextField.StringValue;
            break;
        case "Details":
            prod.Description = view.TextField.StringValue;
            break;
        }
    };

    // Setup view based on the column selected
    switch (tableColumn.Title) {
    case "Product":
        view.ImageView.Image = NSImage.ImageNamed (product.IsProductGroup ? "tags.png" : "tag.png");
        view.TextField.StringValue = product.Title;
        break;
    case "Details":
        view.TextField.StringValue = product.Description;
        break;
    }

    return view;
}

Weitere Informationen finden Sie im Abschnitt Verwenden von Bildern mit Gliederungsansichten unserer Dokumentation zum Arbeiten mit Bildern .

Datenbindungsgliederungsansichten

Durch die Verwendung Key-Value Codierungs- und Datenbindungstechniken in Ihrer Xamarin.Mac-Anwendung können Sie die Menge an Code, den Sie schreiben und verwalten müssen, um Benutzeroberflächenelemente aufzufüllen und zu arbeiten, erheblich verringern. Sie haben auch den Vorteil, Dass Ihre Sicherungsdaten (Datenmodell) weiter von Ihrer Front-End-Benutzeroberfläche (Model-View-Controller) entkoppelt werden, was zu einem einfacheren, flexibleren Anwendungsentwurf führt.

Key-Value Coding (KVC) ist ein Mechanismus für den indirekten Zugriff auf die Eigenschaften eines Objekts, wobei Schlüssel (speziell formatierte Zeichenfolgen) verwendet werden, um Eigenschaften zu identifizieren, anstatt über instance Variablen 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, Kerndaten, Cocoa-Bindungen und Skriptierbarkeit.

Weitere Informationen finden Sie im Abschnitt Datenbindung in der Gliederungsansicht unserer Dokumentation zur Datenbindung und Key-Value Codierung .

Zusammenfassung

In diesem Artikel wird die Arbeit mit Gliederungsansichten in einer Xamarin.Mac-Anwendung ausführlich erläutert. Wir haben die verschiedenen Typen und Verwendungen von Gliederungsansichten, das Erstellen und Verwalten von Gliederungsansichten im Xcode-Schnittstellen-Generator und das Arbeiten mit Gliederungsansichten in C#-Code gesehen.