Widoki kolekcji na platformie Xamarin.Mac
W tym artykule opisano pracę z widokami kolekcji w aplikacji platformy Xamarin.Mac. Obejmuje tworzenie i konserwowanie widoków kolekcji w programie Xcode i narzędziu Interface Builder oraz programowe pracę z nimi.
Podczas pracy z językiem C# i platformą .NET w aplikacji platformy Xamarin.Mac deweloper ma dostęp do tych samych kontrolek widoku kolekcji AppKit, w których pracuje Objective-C deweloper i czy program Xcode . Ponieważ platforma Xamarin.Mac integruje się bezpośrednio z programem Xcode, deweloper używa konstruktora interfejsu Xcode do tworzenia i obsługi widoków kolekcji.
Obiekt NSCollectionView
wyświetla siatkę widoków podrzędnych zorganizowanych przy użyciu elementu NSCollectionViewLayout
. Każdy widok podrzędny w siatce jest reprezentowany przez element NSCollectionViewItem
, który zarządza ładowaniem .xib
zawartości widoku z pliku.
W tym artykule opisano podstawy pracy z widokami kolekcji w aplikacji Xamarin.Mac. Zdecydowanie zaleca się, aby najpierw zapoznać się z artykułem Hello, Mac , w szczególności wprowadzenie do narzędzi Xcode i Interface Builder i Outlets and Actions , ponieważ obejmuje ona kluczowe pojęcia i techniki, które są używane w tym artykule.
Warto zapoznać się również z sekcją Uwidacznianie klas/ metod Objective-C języka C# w dokumencie Xamarin.Mac Internals . Register
Objaśnienie poleceń i Export
używanych do podłączania klas języka C# do Objective-C obiektów i elementów interfejsu użytkownika.
Informacje o widokach kolekcji
Głównym celem widoku kolekcji (NSCollectionView
) jest wizualne rozmieszczenie grupy obiektów w zorganizowany sposób przy użyciu układu widoku kolekcji (), z każdym pojedynczym obiektem (NSCollectionViewLayout
NSCollectionViewItem
) uzyskującym własny widok w większej kolekcji. Widoki kolekcji działają za pomocą technik tworzenia powiązań danych i kodowania klucz-wartość. W związku z tym należy zapoznać się z dokumentacją powiązania danych i kodowania klucz-wartość przed kontynuowaniem pracy z tym artykułem.
Widok kolekcji nie ma standardowego, wbudowanego elementu widoku kolekcji (takiego jak kontur lub widok tabeli), dlatego deweloper jest odpowiedzialny za projektowanie i implementowanie widoku prototypu przy użyciu innych kontrolek AppKit, takich jak Pola obrazów, Pola tekstowe, Etykiety itp. Ten widok prototypu będzie używany do wyświetlania i pracy z każdym elementem zarządzanym .xib
przez widok kolekcji i jest przechowywany w pliku.
Ponieważ deweloper jest odpowiedzialny za wygląd i działanie elementu widoku kolekcji, widok kolekcji nie ma wbudowanej obsługi wyróżniania wybranego elementu w siatce. Zaimplementowanie tej funkcji zostanie omówione w tym artykule.
Definiowanie modelu danych
Przed powiązaniem danych widoku kolekcji w narzędziu Interface Builder należy zdefiniować klasę zgodną ze standardem KVC (Key-Value Observing) /Key-Value Observing (KVO) w aplikacji Xamarin.Mac, aby działać jako model danych dla powiązania. Model danych udostępnia wszystkie dane, które będą wyświetlane w kolekcji i otrzymują wszelkie modyfikacje danych, które użytkownik wprowadza w interfejsie użytkownika podczas uruchamiania aplikacji.
Przykład aplikacji, która zarządza grupą pracowników, można użyć następującej klasy do zdefiniowania modelu danych:
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
}
}
Model PersonModel
danych będzie używany w pozostałej części tego artykułu.
Praca z widokiem kolekcji
Powiązanie danych z widokiem kolekcji jest bardzo podobne do powiązania z widokiem tabeli, ponieważ NSCollectionViewDataSource
służy do udostępniania danych dla kolekcji. Ponieważ widok kolekcji nie ma wstępnie ustawionego formatu wyświetlania, wymagana jest większa praca w celu przekazywania opinii o interakcji użytkownika i śledzenia wyboru użytkownika.
Tworzenie prototypu komórki
Ponieważ widok kolekcji nie zawiera domyślnego prototypu komórki, deweloper będzie musiał dodać jeden lub więcej .xib
plików do aplikacji Xamarin.Mac, aby zdefiniować układ i zawartość poszczególnych komórek.
Należy wykonać następujące czynności:
W Eksplorator rozwiązań kliknij prawym przyciskiem myszy nazwę projektu i wybierz polecenie Dodaj>nowy plik...
Wybierz pozycję Kontroler widoku dla komputerów Mac>, nadaj mu nazwę (na
EmployeeItem
przykład w tym przykładzie) i kliknij przycisk Nowy, aby utworzyć:Spowoduje to dodanie pliku
EmployeeItem.cs
EmployeeItemController.cs
i doEmployeeItemController.xib
rozwiązania projektu.Kliknij dwukrotnie plik, aby otworzyć go do edycji w narzędziu
EmployeeItemController.xib
Xcode Interface Builder.Dodaj kontrolkę i
NSImageView
dwieNSLabel
kontrolkiNSBox
do widoku i ułóż je w następujący sposób:Otwórz Edytor Asystenta i utwórz gniazdo dla
NSBox
elementu , aby można było go użyć do wskazania stanu zaznaczenia komórki:Wróć do edytora standardowego i wybierz widok obrazu.
W inspektorze powiązania wybierz pozycję Powiąż z>właścicielem pliku i wprowadź ścieżkęklucza modelu :
self.Person.Icon
Wybierz pierwszą etykietę, a następnie w inspektorze powiązań wybierz pozycję Powiąż z>właścicielem pliku i wprowadź ścieżkę klucza modelu :
self.Person.Name
Wybierz drugą etykietę, a następnie w inspektorze powiązań wybierz pozycję Powiąż z>właścicielem pliku i wprowadź ścieżkę klucza modelu :
self.Person.Occupation
Zapisz zmiany w
.xib
pliku i wróć do programu Visual Studio, aby zsynchronizować zmiany.
Zmodyfikuj EmployeeItemController.cs
plik i utwórz go w następujący sposób:
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
}
}
Patrząc na ten kod szczegółowo, klasa dziedziczy z NSCollectionViewItem
, aby mogła działać jako prototyp dla komórki Widok kolekcji. Właściwość Person
uwidacznia klasę, która została użyta do powiązania danych z widokiem obrazu i etykietami w programie Xcode. Jest to wystąpienie utworzonego PersonModel
powyżej.
Właściwość BackgroundColor
jest skrótem do kontrolki NSBox
FillColor
, która będzie używana do pokazywania stanu zaznaczenia komórki. Przesłaniając Selected
właściwość NSCollectionViewItem
, następujące zestawy kodu lub czyści ten stan zaznaczenia:
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;
}
}
}
Tworzenie źródła danych widoku kolekcji
Źródło danych widoku kolekcji (NSCollectionViewDataSource
) udostępnia wszystkie dane widoku kolekcji i tworzy i wypełnia komórkę widoku kolekcji (przy użyciu prototypu .xib
) zgodnie z wymaganiami dla każdego elementu w kolekcji.
Dodaj nową klasę projektu, wywołaj go CollectionViewDataSource
i utwórz ją tak, jakby wyglądała następująco:
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
}
}
Patrząc na ten kod szczegółowo, klasa dziedziczy i NSCollectionViewDataSource
uwidacznia listę PersonModel
wystąpień za pośrednictwem jej Data
właściwości.
Ponieważ ta kolekcja ma tylko jedną sekcję, kod zastępuje metodę GetNumberOfSections
i zawsze zwraca wartość 1
. GetNumberofItems
Ponadto metoda jest zastępowana, zwraca liczbę elementów na Data
liście właściwości.
Metoda jest wywoływana GetItem
za każdym razem, gdy jest wymagana nowa komórka i wygląda następująco:
public override NSCollectionViewItem GetItem(NSCollectionView collectionView, NSIndexPath indexPath)
{
var item = collectionView.MakeItem("EmployeeCell", indexPath) as EmployeeItemController;
item.Person = Data[(int)indexPath.Item];
return item;
}
MakeItem
Metoda widoku kolekcji jest wywoływana w celu utworzenia lub zwrócenia wystąpienia wielokrotnego użytku obiektu EmployeeItemController
, a jego Person
właściwość jest ustawiona na element wyświetlany w żądanej komórce.
Element EmployeeItemController
musi być wcześniej zarejestrowany w kontrolerze widoku kolekcji przy użyciu następującego kodu:
EmployeeCollection.RegisterClassForItem(typeof(EmployeeItemController), "EmployeeCell");
Identyfikator (EmployeeCell
) użyty w wywołaniu MakeItem
musi być zgodny z nazwą kontrolera widoku, który został zarejestrowany w widoku kolekcji. Ten krok zostanie szczegółowo omówiony poniżej.
Obsługa zaznaczenia elementu
Aby obsłużyć zaznaczenie i usunięcie zaznaczenia elementów w kolekcji, NSCollectionViewDelegate
będzie wymagane. Ponieważ w tym przykładzie będzie używany wbudowany NSCollectionViewFlowLayout
typ układu, NSCollectionViewDelegateFlowLayout
wymagana będzie określona wersja tego delegata.
Dodaj nową klasę do projektu, wywołaj ją CollectionViewDelegate
i utwórz ją w następujący sposób:
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
}
}
Metody ItemsSelected
i ItemsDeselected
są zastępowane i używane do ustawiania lub czyszczenia PersonSelected
właściwości kontrolera widoku, który obsługuje widok kolekcji, gdy użytkownik wybiera lub usuwa zaznaczenie elementu. Zostanie to pokazane szczegółowo poniżej.
Tworzenie widoku kolekcji w narzędziu Interface Builder
Ze wszystkimi wymaganymi elementami pomocniczymi można edytować główny scenorys i dodać do niego widok kolekcji.
Należy wykonać następujące czynności:
Main.Storyboard
Kliknij dwukrotnie plik w Eksplorator rozwiązań, aby otworzyć go do edycji w narzędziu Xcode Interface Builder.Przeciągnij widok kolekcji do widoku głównego i zmień jego rozmiar, aby wypełnić widok:
Po wybraniu widoku kolekcji użyj edytora ograniczeń, aby przypiąć go do widoku po zmianie rozmiaru:
Upewnij się, że widok kolekcji jest zaznaczony na powierzchni projektowej (a nie w widoku obramowania przewijania lub wycinek, który go zawiera), przejdź do Edytora Asystenta i utwórz gniazdo dla widoku kolekcji:
Zapisz zmiany i wróć do programu Visual Studio, aby przeprowadzić synchronizację.
Łączenie tego wszystkiego razem
Wszystkie elementy pomocnicze zostały teraz wprowadzone z klasą do działania jako model danych (PersonModel
), dodano element do dostarczania danych, utworzono element NSCollectionViewDelegateFlowLayout
do obsługi wyboru elementów i NSCollectionView
element został dodany do głównego scenorysu i uwidoczniony jako gniazdo (EmployeeCollection
NSCollectionViewDataSource
).
Ostatnim krokiem jest edytowanie kontrolera widoku zawierającego widok kolekcji i przeniesienie wszystkich elementów w celu wypełnienia kolekcji i obsługi zaznaczenia elementu.
Zmodyfikuj ViewController.cs
plik i utwórz go w następujący sposób:
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
}
}
Przyjrzyjmy się szczegółowo temu kodowi, Datasource
a właściwość jest definiowana w celu przechowywania wystąpienia CollectionViewDataSource
obiektu , które będzie dostarczać dane dla widoku kolekcji. Właściwość PersonSelected
jest definiowana do przechowywania PersonModel
reprezentującego aktualnie wybranego elementu w widoku kolekcji. Ta właściwość zgłasza SelectionChanged
również zdarzenie, gdy wybór ulegnie zmianie.
Klasa ConfigureCollectionView
służy do rejestrowania kontrolera widoku, który działa jako prototyp komórki w widoku kolekcji przy użyciu następującego wiersza:
EmployeeCollection.RegisterClassForItem(typeof(EmployeeItemController), "EmployeeCell");
Zwróć uwagę, że identyfikator (EmployeeCell
) użyty do zarejestrowania prototypu jest zgodny z identyfikatorem wywołanym w GetItem
metodzie zdefiniowanej CollectionViewDataSource
powyżej:
var item = collectionView.MakeItem("EmployeeCell", indexPath) as EmployeeItemController;
...
Ponadto typ kontrolera widoku musi być zgodny z nazwą .xib
pliku, który dokładnie definiuje prototyp. W przypadku tego przykładu EmployeeItemController
i EmployeeItemController.xib
.
Rzeczywisty układ elementów w widoku kolekcji jest kontrolowany przez klasę Układ widoku kolekcji i można go dynamicznie zmieniać w czasie wykonywania, przypisując nowe wystąpienie do CollectionViewLayout
właściwości . Zmiana tej właściwości powoduje zaktualizowanie wyglądu widoku kolekcji bez animowania zmiany.
Firma Apple dostarcza dwa wbudowane typy układów z widokiem kolekcji, które będą obsługiwać najbardziej typowe zastosowania: NSCollectionViewFlowLayout
i NSCollectionViewGridLayout
. Jeśli deweloper wymaga formatu niestandardowego, takiego jak układanie elementów w okręgu, może utworzyć niestandardowe wystąpienie NSCollectionViewLayout
i zastąpić wymagane metody, aby osiągnąć pożądany efekt.
W tym przykładzie użyto domyślnego NSCollectionViewFlowLayout
układu przepływu, aby utworzyć wystąpienie klasy i skonfigurować go w następujący sposób:
var flowLayout = new NSCollectionViewFlowLayout()
{
ItemSize = new CGSize(150, 150),
SectionInset = new NSEdgeInsets(10, 10, 10, 20),
MinimumInteritemSpacing = 10,
MinimumLineSpacing = 10
};
Właściwość ItemSize
definiuje rozmiar każdej pojedynczej komórki w kolekcji. Właściwość SectionInset
definiuje zestawy z krawędzi kolekcji, w których będą rozmieszczone komórki. MinimumInteritemSpacing
definiuje minimalne odstępy między elementami i MinimumLineSpacing
definiuje minimalne odstępy między wierszami w kolekcji.
Układ jest przypisywany do widoku kolekcji, a wystąpienie elementu CollectionViewDelegate
jest dołączone do obsługi zaznaczenia elementu:
// Setup collection view
EmployeeCollection.CollectionViewLayout = flowLayout;
EmployeeCollection.Delegate = new CollectionViewDelegate(this);
Metoda PopulateWithData
tworzy nowe wystąpienie CollectionViewDataSource
obiektu , wypełnia je danymi, dołącza je do widoku kolekcji i wywołuje ReloadData
metodę w celu wyświetlenia elementów:
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();
}
Metoda ViewDidLoad
jest zastępowana i wywołuje ConfigureCollectionView
metody i PopulateWithData
w celu wyświetlenia końcowego widoku kolekcji użytkownikowi:
public override void ViewDidLoad()
{
base.ViewDidLoad();
// Initialize Collection View
ConfigureCollectionView();
PopulateWithData();
}
Podsumowanie
W tym artykule szczegółowo przedstawiono pracę z widokami kolekcji w aplikacji platformy Xamarin.Mac. Najpierw przyjrzeliśmy się uwidacznieniu klasy Objective-C C# przy użyciu kodowania klucz-wartość (KVC) i obserwowania wartości klucz-wartość (KVO). Następnie pokazano, jak używać klasy zgodnej z KVO i powiązać je z widokami kolekcji w narzędziu Interface Builder programu Xcode. Na koniec pokazano, jak korzystać z widoków kolekcji w kodzie języka C#.