Sammlungsansichten in Xamarin.Mac
In diesem Artikel wird das Arbeiten mit Sammlungsansichten in einer Xamarin.Mac-App beschrieben. Es behandelt das Erstellen und Standard Beibehalten von Sammlungsansichten in Xcode und Interface Builder und die programmgesteuerte Arbeit mit ihnen.
Beim Arbeiten mit C# und .NET in einer Xamarin.Mac-App hat der Entwickler Zugriff auf die gleichen AppKit-Sammlungsansichtssteuerelemente, in Objective-C denen ein Entwickler arbeitet und Xcode ausführt. Da Xamarin.Mac direkt in Xcode integriert wird, verwendet der Entwickler den Schnittstellen-Generator von Xcode zum Erstellen und Standard tain-Sammlungsansichten.
A NSCollectionView
displays a grid of subviews organized using a NSCollectionViewLayout
. Jede Unteransicht im Raster wird durch eine NSCollectionViewItem
Darstellung dargestellt, die das Laden des Inhalts der Ansicht aus einer .xib
Datei verwaltet.
In diesem Artikel werden die Grundlagen der Arbeit mit Sammlungsansichten in einer Xamarin.Mac-App 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 "Actions ", da sie wichtige Konzepte und Techniken behandelt, die in diesem Artikel verwendet 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.
Informationen zu Sammlungsansichten
Das Standard Ziel einer Sammlungsansicht (NSCollectionView
) besteht darin, eine Gruppe von Objekten mithilfe eines Sammlungsansichtslayouts () visuell anzuordnen, wobei jedes einzelne Objekt (NSCollectionViewLayout
NSCollectionViewItem
) seine eigene Ansicht in der größeren Auflistung erhält. Sammlungsansichten funktionieren über Datenbindungs- und Schlüsselwertcodierungstechniken. Daher sollten Sie die Dokumentation "Datenbindung" und "Key-Value Coding " lesen, bevor Sie mit diesem Artikel fortfahren.
Die Sammlungsansicht verfügt über kein standardmäßiges, integriertes Sammlungsansichtselement (z. B. eine Gliederungs- oder Tabellenansicht), sodass der Entwickler für das Entwerfen und Implementieren einer Prototypansicht mithilfe anderer AppKit-Steuerelemente wie Bildfelder, Textfelder, Bezeichnungen usw. verantwortlich ist. Diese Prototypansicht wird verwendet, um jedes Element anzuzeigen und zu arbeiten, das von der Sammlungsansicht verwaltet wird und in einer .xib
Datei gespeichert wird.
Da der Entwickler für das Aussehen und Verhalten eines Sammlungsansichtselements verantwortlich ist, bietet die Sammlungsansicht keine integrierte Unterstützung zum Hervorheben eines ausgewählten Elements im Raster. Die Implementierung dieses Features wird in diesem Artikel behandelt.
Definieren des Datenmodells
Vor der Datenbindung einer Sammlungsansicht im Schnittstellen-Generator muss eine KVC-kompatible Klasse (Key-Value Coding)/Key-Value Observing (KVO) in der Xamarin.Mac-App definiert werden, um als Datenmodell für die Bindung zu fungieren. Das Datenmodell stellt alle Daten bereit, die in der Sammlung angezeigt werden, und empfängt alle Änderungen an den Daten, die der Benutzer in der Benutzeroberfläche während der Ausführung der Anwendung vornimmt.
Nehmen Sie sich das Beispiel einer App, die eine Gruppe von Mitarbeitern verwaltet, die folgende Klasse zum Definieren des Datenmodells verwendet werden kann:
using System;
using Foundation;
using AppKit;
namespace MacDatabinding
{
[Register("PersonModel")]
public class PersonModel : NSObject
{
#region Private Variables
private string _name = "";
private string _occupation = "";
private bool _isManager = false;
private NSMutableArray _people = new NSMutableArray();
#endregion
#region Computed Properties
[Export("Name")]
public string Name {
get { return _name; }
set {
WillChangeValue ("Name");
_name = value;
DidChangeValue ("Name");
}
}
[Export("Occupation")]
public string Occupation {
get { return _occupation; }
set {
WillChangeValue ("Occupation");
_occupation = value;
DidChangeValue ("Occupation");
}
}
[Export("isManager")]
public bool isManager {
get { return _isManager; }
set {
WillChangeValue ("isManager");
WillChangeValue ("Icon");
_isManager = value;
DidChangeValue ("isManager");
DidChangeValue ("Icon");
}
}
[Export("isEmployee")]
public bool isEmployee {
get { return (NumberOfEmployees == 0); }
}
[Export("Icon")]
public NSImage Icon
{
get
{
if (isManager)
{
return NSImage.ImageNamed("IconGroup");
}
else
{
return NSImage.ImageNamed("IconUser");
}
}
}
[Export("personModelArray")]
public NSArray People {
get { return _people; }
}
[Export("NumberOfEmployees")]
public nint NumberOfEmployees {
get { return (nint)_people.Count; }
}
#endregion
#region Constructors
public PersonModel ()
{
}
public PersonModel (string name, string occupation)
{
// Initialize
this.Name = name;
this.Occupation = occupation;
}
public PersonModel (string name, string occupation, bool manager)
{
// Initialize
this.Name = name;
this.Occupation = occupation;
this.isManager = manager;
}
#endregion
#region Array Controller Methods
[Export("addObject:")]
public void AddPerson(PersonModel person) {
WillChangeValue ("personModelArray");
isManager = true;
_people.Add (person);
DidChangeValue ("personModelArray");
}
[Export("insertObject:inPersonModelArrayAtIndex:")]
public void InsertPerson(PersonModel person, nint index) {
WillChangeValue ("personModelArray");
_people.Insert (person, index);
DidChangeValue ("personModelArray");
}
[Export("removeObjectFromPersonModelArrayAtIndex:")]
public void RemovePerson(nint index) {
WillChangeValue ("personModelArray");
_people.RemoveObject (index);
DidChangeValue ("personModelArray");
}
[Export("setPersonModelArray:")]
public void SetPeople(NSMutableArray array) {
WillChangeValue ("personModelArray");
_people = array;
DidChangeValue ("personModelArray");
}
#endregion
}
}
Das PersonModel
Datenmodell wird während des restlichen Artikels verwendet.
Arbeiten mit einer Sammlungsansicht
Die Datenbindung mit einer Sammlungsansicht ähnelt der Bindung mit einer Tabellenansicht, wie NSCollectionViewDataSource
sie zum Bereitstellen von Daten für die Sammlung verwendet wird. Da die Sammlungsansicht nicht über ein voreingestelltes Anzeigeformat verfügt, ist mehr Arbeit erforderlich, um Feedback zur Benutzerinteraktion bereitzustellen und die Benutzerauswahl nachzuverfolgen.
Erstellen des Zellprototyps
Da die Sammlungsansicht keinen Standardzellenprototyp enthält, muss der Entwickler der Xamarin.Mac-App mindestens eine .xib
Datei hinzufügen, um das Layout und den Inhalt der einzelnen Zellen zu definieren.
Gehen Sie folgendermaßen vor:
Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf den Projektnamen, und wählen Sie "Neue Datei hinzufügen>" aus...
Wählen Sie Mac-Ansichtscontroller aus, geben Sie ihm einen Namen (z
EmployeeItem
. B. in diesem Beispiel), und klicken Sie auf die Schaltfläche "Neu", um folgendes zu erstellen:>Dadurch wird der Projektmappe eine Datei
EmployeeItemController.cs
undEmployeeItemController.xib
eineEmployeeItem.cs
Datei hinzugefügt.Doppelklicken Sie auf die
EmployeeItemController.xib
Datei, um sie zum Bearbeiten im Schnittstellen-Generator von Xcode zu öffnen.Fügen Sie der Ansicht ein
NSBox
undNSImageView
zweiNSLabel
Steuerelemente hinzu, und legen Sie sie wie folgt an:Öffnen Sie den Assistenten-Editor , und erstellen Sie eine Steckdose ,
NSBox
damit sie verwendet werden kann, um den Auswahlstatus einer Zelle anzugeben:Kehren Sie zum Standard-Editor zurück, und wählen Sie die Bildansicht aus.
Wählen Sie im Bindungsinspektor die Option "An Dateibesitzer binden>" aus, und geben Sie einen Modellschlüsselpfad von
self.Person.Icon
:Wählen Sie die erste Bezeichnung aus, und wählen Sie im Bindungsinspektor die Option "An Dateibesitzer binden>" aus, und geben Sie einen Modellschlüsselpfad ein:
self.Person.Name
Wählen Sie die zweite Bezeichnung und im Bindungsinspektor die Option "An Dateibesitzer binden>" aus, und geben Sie einen Modellschlüsselpfad ein:
self.Person.Occupation
Speichern Sie die Änderungen an der
.xib
Datei, und kehren Sie zu Visual Studio zurück, um die Änderungen zu synchronisieren.
Bearbeiten Sie die EmployeeItemController.cs
Datei, und stellen Sie sicher, dass sie wie folgt aussieht:
using System;
using System.Collections.Generic;
using System.Linq;
using Foundation;
using AppKit;
namespace MacCollectionNew
{
/// <summary>
/// The Employee item controller handles the display of the individual items that will
/// be displayed in the collection view as defined in the associated .XIB file.
/// </summary>
public partial class EmployeeItemController : NSCollectionViewItem
{
#region Private Variables
/// <summary>
/// The person that will be displayed.
/// </summary>
private PersonModel _person;
#endregion
#region Computed Properties
// strongly typed view accessor
public new EmployeeItem View
{
get
{
return (EmployeeItem)base.View;
}
}
/// <summary>
/// Gets or sets the person.
/// </summary>
/// <value>The person that this item belongs to.</value>
[Export("Person")]
public PersonModel Person
{
get { return _person; }
set
{
WillChangeValue("Person");
_person = value;
DidChangeValue("Person");
}
}
/// <summary>
/// Gets or sets the color of the background for the item.
/// </summary>
/// <value>The color of the background.</value>
public NSColor BackgroundColor {
get { return Background.FillColor; }
set { Background.FillColor = value; }
}
/// <summary>
/// Gets or sets a value indicating whether this <see cref="T:MacCollectionNew.EmployeeItemController"/> is selected.
/// </summary>
/// <value><c>true</c> if selected; otherwise, <c>false</c>.</value>
/// <remarks>This also changes the background color based on the selected state
/// of the item.</remarks>
public override bool Selected
{
get
{
return base.Selected;
}
set
{
base.Selected = value;
// Set background color based on the selection state
if (value) {
BackgroundColor = NSColor.DarkGray;
} else {
BackgroundColor = NSColor.LightGray;
}
}
}
#endregion
#region Constructors
// Called when created from unmanaged code
public EmployeeItemController(IntPtr handle) : base(handle)
{
Initialize();
}
// Called when created directly from a XIB file
[Export("initWithCoder:")]
public EmployeeItemController(NSCoder coder) : base(coder)
{
Initialize();
}
// Call to load from the XIB/NIB file
public EmployeeItemController() : base("EmployeeItem", NSBundle.MainBundle)
{
Initialize();
}
// Added to support loading from XIB/NIB
public EmployeeItemController(string nibName, NSBundle nibBundle) : base(nibName, nibBundle) {
Initialize();
}
// Shared initialization code
void Initialize()
{
}
#endregion
}
}
Wenn Sie diesen Code im Detail betrachten, erbt die Klasse, NSCollectionViewItem
damit sie als Prototyp für eine Sammlungsansichtszelle fungieren kann. Die Person
Eigenschaft macht die Klasse verfügbar, die zum Binden an die Bildansicht und beschriftungen in Xcode verwendet wurde. Dies ist eine Instanz der PersonModel
oben erstellten.
Die BackgroundColor
Eigenschaft ist eine Verknüpfung mit dem NSBox
Steuerelement FillColor
, das verwendet wird, um den Auswahlstatus einer Zelle anzuzeigen. Durch Überschreiben der Selected
Eigenschaft des NSCollectionViewItem
Codes wird dieser Auswahlzustand durch den folgenden Code festgelegt oder gelöscht:
public override bool Selected
{
get
{
return base.Selected;
}
set
{
base.Selected = value;
// Set background color based on the selection state
if (value) {
BackgroundColor = NSColor.DarkGray;
} else {
BackgroundColor = NSColor.LightGray;
}
}
}
Erstellen der Datenquelle für die Sammlungsansicht
Eine Sammlungsansicht-Datenquelle (NSCollectionViewDataSource
) stellt alle Daten für eine Sammlungsansicht bereit und erstellt und füllt eine Sammlungsansichtszelle (mithilfe des .xib
Prototyps) nach Bedarf für jedes Element in der Auflistung auf.
Fügen Sie eine neue Klasse des Projekts hinzu, nennen Sie sie CollectionViewDataSource
, und stellen Sie sicher, dass sie wie folgt aussieht:
using System;
using System.Collections.Generic;
using AppKit;
using Foundation;
namespace MacCollectionNew
{
/// <summary>
/// Collection view data source provides the data for the collection view.
/// </summary>
public class CollectionViewDataSource : NSCollectionViewDataSource
{
#region Computed Properties
/// <summary>
/// Gets or sets the parent collection view.
/// </summary>
/// <value>The parent collection view.</value>
public NSCollectionView ParentCollectionView { get; set; }
/// <summary>
/// Gets or sets the data that will be displayed in the collection.
/// </summary>
/// <value>A collection of PersonModel objects.</value>
public List<PersonModel> Data { get; set; } = new List<PersonModel>();
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="T:MacCollectionNew.CollectionViewDataSource"/> class.
/// </summary>
/// <param name="parent">The parent collection that this datasource will provide data for.</param>
public CollectionViewDataSource(NSCollectionView parent)
{
// Initialize
ParentCollectionView = parent;
// Attach to collection view
parent.DataSource = this;
}
#endregion
#region Override Methods
/// <summary>
/// Gets the number of sections.
/// </summary>
/// <returns>The number of sections.</returns>
/// <param name="collectionView">The parent Collection view.</param>
public override nint GetNumberOfSections(NSCollectionView collectionView)
{
// There is only one section in this view
return 1;
}
/// <summary>
/// Gets the number of items in the given section.
/// </summary>
/// <returns>The number of items.</returns>
/// <param name="collectionView">The parent Collection view.</param>
/// <param name="section">The Section number to count items for.</param>
public override nint GetNumberofItems(NSCollectionView collectionView, nint section)
{
// Return the number of items
return Data.Count;
}
/// <summary>
/// Gets the item for the give section and item index.
/// </summary>
/// <returns>The item.</returns>
/// <param name="collectionView">The parent Collection view.</param>
/// <param name="indexPath">Index path specifying the section and index.</param>
public override NSCollectionViewItem GetItem(NSCollectionView collectionView, NSIndexPath indexPath)
{
var item = collectionView.MakeItem("EmployeeCell", indexPath) as EmployeeItemController;
item.Person = Data[(int)indexPath.Item];
return item;
}
#endregion
}
}
Im Detail wird dieser Code von der Klasse geerbt NSCollectionViewDataSource
und eine Liste von PersonModel
Instanzen über ihre Data
Eigenschaft verfügbar gemacht.
Da diese Auflistung nur über einen Abschnitt verfügt, überschreibt der Code die GetNumberOfSections
Methode und gibt immer zurück 1
. Darüber hinaus wird die GetNumberofItems
Methode überschrieben, um die Anzahl der Elemente in der Data
Eigenschaftsliste zurückgibt.
Die GetItem
Methode wird immer aufgerufen, wenn eine neue Zelle erforderlich ist und wie folgt aussieht:
public override NSCollectionViewItem GetItem(NSCollectionView collectionView, NSIndexPath indexPath)
{
var item = collectionView.MakeItem("EmployeeCell", indexPath) as EmployeeItemController;
item.Person = Data[(int)indexPath.Item];
return item;
}
Die MakeItem
Methode der Sammlungsansicht wird aufgerufen, um eine wiederverwendbare Instanz der EmployeeItemController
Auflistungsansicht zu erstellen oder zurückzugeben, und ihre Person
Eigenschaft wird auf das Element festgelegt, das in der angeforderten Zelle angezeigt wird.
Der EmployeeItemController
Code muss vorab mit dem Sammlungsansichtscontroller registriert werden:
EmployeeCollection.RegisterClassForItem(typeof(EmployeeItemController), "EmployeeCell");
Der im MakeItem
Aufruf verwendete Bezeichner (EmployeeCell
) muss mit dem Namen des Ansichtscontrollers übereinstimmen, der bei der Sammlungsansicht registriert wurde. Dieser Schritt wird unten ausführlich behandelt.
Behandeln der Elementauswahl
Zum Behandeln der Auswahl und Deselection von Elementen in der Auflistung ist eine NSCollectionViewDelegate
erforderlich. Da in diesem Beispiel der integrierte NSCollectionViewFlowLayout
Layouttyp verwendet wird, ist eine NSCollectionViewDelegateFlowLayout
bestimmte Version dieses Delegaten erforderlich.
Fügen Sie dem Projekt eine neue Klasse hinzu, rufen Sie sie CollectionViewDelegate
auf, und stellen Sie sicher, dass sie wie folgt aussieht:
using System;
using Foundation;
using AppKit;
namespace MacCollectionNew
{
/// <summary>
/// Collection view delegate handles user interaction with the elements of the
/// collection view for the Flow-Based layout type.
/// </summary>
public class CollectionViewDelegate : NSCollectionViewDelegateFlowLayout
{
#region Computed Properties
/// <summary>
/// Gets or sets the parent view controller.
/// </summary>
/// <value>The parent view controller.</value>
public ViewController ParentViewController { get; set; }
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="T:MacCollectionNew.CollectionViewDelegate"/> class.
/// </summary>
/// <param name="parentViewController">Parent view controller.</param>
public CollectionViewDelegate(ViewController parentViewController)
{
// Initialize
ParentViewController = parentViewController;
}
#endregion
#region Override Methods
/// <summary>
/// Handles one or more items being selected.
/// </summary>
/// <param name="collectionView">The parent Collection view.</param>
/// <param name="indexPaths">The Index paths of the items being selected.</param>
public override void ItemsSelected(NSCollectionView collectionView, NSSet indexPaths)
{
// Dereference path
var paths = indexPaths.ToArray<NSIndexPath>();
var index = (int)paths[0].Item;
// Save the selected item
ParentViewController.PersonSelected = ParentViewController.Datasource.Data[index];
}
/// <summary>
/// Handles one or more items being deselected.
/// </summary>
/// <param name="collectionView">The parent Collection view.</param>
/// <param name="indexPaths">The Index paths of the items being deselected.</param>
public override void ItemsDeselected(NSCollectionView collectionView, NSSet indexPaths)
{
// Dereference path
var paths = indexPaths.ToArray<NSIndexPath>();
var index = paths[0].Item;
// Clear selection
ParentViewController.PersonSelected = null;
}
#endregion
}
}
Die ItemsSelected
Methoden ItemsDeselected
werden überschrieben und zum Festlegen oder Löschen der PersonSelected
Eigenschaft des Ansichtscontrollers verwendet, der die Sammlungsansicht behandelt, wenn der Benutzer ein Element auswählt oder deaktiviert. Dies wird unten im Detail angezeigt.
Erstellen der Sammlungsansicht im Schnittstellen-Generator
Da alle erforderlichen Unterstützenden elemente vorhanden sind, kann das Standard Storyboard bearbeitet und eine Sammlungsansicht hinzugefügt werden.
Gehen Sie folgendermaßen vor:
Doppelklicken Sie auf die
Main.Storyboard
Datei im Projektmappen-Explorer, um sie zum Bearbeiten im Schnittstellen-Generator von Xcode zu öffnen.Ziehen Sie eine Sammlungsansicht in die Hauptansicht, und ändern Sie die Größe, um die Ansicht auszufüllen:
Wenn die Sammlungsansicht ausgewählt ist, verwenden Sie den Einschränkungs-Editor, um sie an die Ansicht anzuheften, wenn die Größe geändert wird:
Stellen Sie sicher, dass die Sammlungsansicht in der Entwurfsoberfläche ausgewählt ist (und nicht die gerahmente Bildlaufansicht oder Clip View, die sie enthält), wechseln Sie zum Assistenten-Editor, und erstellen Sie eine Steckdose für die Sammlungsansicht:
Speichern Sie die Änderungen, und kehren Sie zur Synchronisierung zu Visual Studio zurück.
Alles zusammenbringen
Alle unterstützenden Teile wurden nun mit einer Klasse platziert, die als Datenmodell (PersonModel
), eine NSCollectionViewDataSource
hinzugefügt wurde, um Daten zu liefern, eine NSCollectionViewDelegateFlowLayout
wurde erstellt, um die Elementauswahl zu behandeln und eine NSCollectionView
wurde dem Main Storyboard hinzugefügt und als Outlet (EmployeeCollection
) verfügbar gemacht.
Der letzte Schritt besteht darin, den Ansichtscontroller zu bearbeiten, der die Sammlungsansicht enthält, und alle Teile zusammenzuführen, um die Sammlung aufzufüllen und die Elementauswahl zu behandeln.
Bearbeiten Sie die ViewController.cs
Datei, und stellen Sie sicher, dass sie wie folgt aussieht:
using System;
using AppKit;
using Foundation;
using CoreGraphics;
namespace MacCollectionNew
{
/// <summary>
/// The View controller controls the main view that houses the Collection View.
/// </summary>
public partial class ViewController : NSViewController
{
#region Private Variables
private PersonModel _personSelected;
private bool shouldEdit = true;
#endregion
#region Computed Properties
/// <summary>
/// Gets or sets the datasource that provides the data to display in the
/// Collection View.
/// </summary>
/// <value>The datasource.</value>
public CollectionViewDataSource Datasource { get; set; }
/// <summary>
/// Gets or sets the person currently selected in the collection view.
/// </summary>
/// <value>The person selected or <c>null</c> if no person is selected.</value>
[Export("PersonSelected")]
public PersonModel PersonSelected
{
get { return _personSelected; }
set
{
WillChangeValue("PersonSelected");
_personSelected = value;
DidChangeValue("PersonSelected");
RaiseSelectionChanged();
}
}
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="T:MacCollectionNew.ViewController"/> class.
/// </summary>
/// <param name="handle">Handle.</param>
public ViewController(IntPtr handle) : base(handle)
{
}
#endregion
#region Override Methods
/// <summary>
/// Called after the view has finished loading from the Storyboard to allow it to
/// be configured before displaying to the user.
/// </summary>
public override void ViewDidLoad()
{
base.ViewDidLoad();
// Initialize Collection View
ConfigureCollectionView();
PopulateWithData();
}
#endregion
#region Private Methods
/// <summary>
/// Configures the collection view.
/// </summary>
private void ConfigureCollectionView()
{
EmployeeCollection.RegisterClassForItem(typeof(EmployeeItemController), "EmployeeCell");
// Create a flow layout
var flowLayout = new NSCollectionViewFlowLayout()
{
ItemSize = new CGSize(150, 150),
SectionInset = new NSEdgeInsets(10, 10, 10, 20),
MinimumInteritemSpacing = 10,
MinimumLineSpacing = 10
};
EmployeeCollection.WantsLayer = true;
// Setup collection view
EmployeeCollection.CollectionViewLayout = flowLayout;
EmployeeCollection.Delegate = new CollectionViewDelegate(this);
}
/// <summary>
/// Populates the Datasource with data and attaches it to the collection view.
/// </summary>
private void PopulateWithData()
{
// Make datasource
Datasource = new CollectionViewDataSource(EmployeeCollection);
// Build list of employees
Datasource.Data.Add(new PersonModel("Craig Dunn", "Documentation Manager", true));
Datasource.Data.Add(new PersonModel("Amy Burns", "Technical Writer"));
Datasource.Data.Add(new PersonModel("Joel Martinez", "Web & Infrastructure"));
Datasource.Data.Add(new PersonModel("Kevin Mullins", "Technical Writer"));
Datasource.Data.Add(new PersonModel("Mark McLemore", "Technical Writer"));
Datasource.Data.Add(new PersonModel("Tom Opgenorth", "Technical Writer"));
Datasource.Data.Add(new PersonModel("Larry O'Brien", "API Docs Manager", true));
Datasource.Data.Add(new PersonModel("Mike Norman", "API Documentor"));
// Populate collection view
EmployeeCollection.ReloadData();
}
#endregion
#region Events
/// <summary>
/// Selection changed delegate.
/// </summary>
public delegate void SelectionChangedDelegate();
/// <summary>
/// Occurs when selection changed.
/// </summary>
public event SelectionChangedDelegate SelectionChanged;
/// <summary>
/// Raises the selection changed event.
/// </summary>
internal void RaiseSelectionChanged() {
// Inform caller
if (this.SelectionChanged != null) SelectionChanged();
}
#endregion
}
}
Im Detail dieses Codes wird eine Datasource
Eigenschaft definiert, um eine Instanz der CollectionViewDataSource
Daten für die Sammlungsansicht bereitzustellen. Eine PersonSelected
Eigenschaft wird definiert, um das PersonModel
aktuell ausgewählte Element in der Sammlungsansicht darzustellen. Diese Eigenschaft löst auch das SelectionChanged
Ereignis aus, wenn sich die Auswahl ändert.
Die ConfigureCollectionView
Klasse wird verwendet, um den Ansichtscontroller zu registrieren, der als Zellprototyp mit der Sammlungsansicht mit der folgenden Zeile fungiert:
EmployeeCollection.RegisterClassForItem(typeof(EmployeeItemController), "EmployeeCell");
Beachten Sie, dass der zum Registrieren des Prototyps verwendete BezeichnerEmployeeCell
dem in der GetItem
oben definierten Methode CollectionViewDataSource
aufgerufenen entspricht:
var item = collectionView.MakeItem("EmployeeCell", indexPath) as EmployeeItemController;
...
Darüber hinaus muss der Typ des Ansichtscontrollers mit dem Namen der .xib
Datei übereinstimmen, die den Prototyp genau definiert. Im Fall dieses Beispiels EmployeeItemController
und EmployeeItemController.xib
.
Das tatsächliche Layout der Elemente in der Sammlungsansicht wird durch eine Sammlungsansichtslayoutklasse gesteuert und kann zur Laufzeit dynamisch geändert werden, indem der CollectionViewLayout
Eigenschaft eine neue Instanz zugewiesen wird. Wenn Sie diese Eigenschaft ändern, wird die Darstellung der Sammlungsansicht aktualisiert, ohne die Änderung zu animieren.
Apple enthält zwei integrierte Layouttypen mit der Sammlungsansicht, die die meisten typischen Verwendungen behandelt: NSCollectionViewFlowLayout
und NSCollectionViewGridLayout
. Wenn der Entwickler ein benutzerdefiniertes Format benötigt hat, z. B. das Platzieren der Elemente in einem Kreis, kann er eine benutzerdefinierte Instanz erstellen NSCollectionViewLayout
und die erforderlichen Methoden überschreiben, um den gewünschten Effekt zu erzielen.
In diesem Beispiel wird das Standardflusslayout verwendet, sodass eine Instanz der NSCollectionViewFlowLayout
Klasse erstellt und wie folgt konfiguriert wird:
var flowLayout = new NSCollectionViewFlowLayout()
{
ItemSize = new CGSize(150, 150),
SectionInset = new NSEdgeInsets(10, 10, 10, 20),
MinimumInteritemSpacing = 10,
MinimumLineSpacing = 10
};
Die ItemSize
Eigenschaft definiert die Größe jeder einzelnen Zelle in der Auflistung. Die SectionInset
Eigenschaft definiert die Einsets vom Rand der Auflistung, in der Zellen angeordnet werden. MinimumInteritemSpacing
definiert den minimalen Abstand zwischen Elementen und MinimumLineSpacing
definiert den minimalen Abstand zwischen Zeilen in der Auflistung.
Das Layout wird der Sammlungsansicht zugewiesen und eine Instanz der CollectionViewDelegate
Elementauswahl zugeordnet:
// Setup collection view
EmployeeCollection.CollectionViewLayout = flowLayout;
EmployeeCollection.Delegate = new CollectionViewDelegate(this);
Die PopulateWithData
Methode erstellt eine neue Instanz des Objekts CollectionViewDataSource
, füllt sie mit Daten auf, fügt sie an die Sammlungsansicht an und ruft die ReloadData
Methode auf, um die Elemente anzuzeigen:
private void PopulateWithData()
{
// Make datasource
Datasource = new CollectionViewDataSource(EmployeeCollection);
// Build list of employees
Datasource.Data.Add(new PersonModel("Craig Dunn", "Documentation Manager", true));
...
// Populate collection view
EmployeeCollection.ReloadData();
}
Die ViewDidLoad
Methode wird außer Kraft gesetzt und ruft die ConfigureCollectionView
methoden auf PopulateWithData
, um die endgültige Sammlungsansicht für den Benutzer anzuzeigen:
public override void ViewDidLoad()
{
base.ViewDidLoad();
// Initialize Collection View
ConfigureCollectionView();
PopulateWithData();
}
Zusammenfassung
Dieser Artikel hat einen detaillierten Blick auf die Arbeit mit Sammlungsansichten in einer Xamarin.Mac-Anwendung genommen. Zunächst wurde untersucht, wie eine C#-Klasse Objective-C mithilfe von Key-Value Coding (KVC) und Key-Value Observing (KVO) verfügbar wird. Als Nächstes wurde gezeigt, wie sie eine KVO-kompatible Klasse und datenbindung an Sammlungsansichten im Schnittstellen-Generator von Xcode verwenden. Schließlich wurde gezeigt, wie sie mit Sammlungsansichten im C#-Code interagieren.