Zobrazení kolekcí v Xamarin.Mac

Tento článek popisuje práci se zobrazeními kolekce v aplikaci Xamarin.Mac. Zabývá se vytvářením a údržbou zobrazení kolekcí v Xcode a Interface Builderu a pracuje s nimi programově.

Při práci s jazykem C# a .NET v aplikaci Xamarin.Mac má vývojář přístup ke stejným ovládacím prvkům zobrazení kolekce AppKit, ve Objective-C které vývojář pracuje a Xcode . Vzhledem k tomu, že se Xamarin.Mac integruje přímo s Xcode, vývojář používá Tvůrce rozhraní Xcode k vytváření a údržbě zobrazení kolekcí.

A NSCollectionView zobrazí mřížku dílčích zobrazení uspořádaných pomocí objektu NSCollectionViewLayout. Každé dílčí zobrazení v mřížce je reprezentováno NSCollectionViewItem načtením obsahu zobrazení ze .xib souboru.

Příklad spuštění aplikace

Tento článek popisuje základy práce se zobrazeními kolekce v aplikaci Xamarin.Mac. Důrazně doporučujeme, abyste si nejprve prošli článek Hello, Mac , konkrétně úvod do Xcode a Tvůrce rozhraní a výstupy a akce , protože se zabývá klíčovými koncepty a technikami, které se používají v tomto článku.

Možná se také budete chtít podívat na oddíly v dokumentu Interní dokumenty Xamarin.Mac pro zveřejnění tříd a metodObjective-Cjazyka C#. Vysvětluje také, které Register příkazy a Export které se používají k připojení tříd jazyka C# k Objective-C objektům a prvkům uživatelského rozhraní.

O zobrazeních kolekce

Hlavním cílem zobrazení kolekce (NSCollectionView) je vizuálně uspořádat skupinu objektů uspořádaným způsobem pomocí rozložení zobrazení kolekce (NSCollectionViewLayout), přičemž každý jednotlivý objekt (NSCollectionViewItem) získá vlastní zobrazení ve větší kolekci. Zobrazení kolekcí fungují prostřednictvím technik kódování datových vazeb a klíč-hodnota. Před pokračováním v tomto článku byste si měli přečíst dokumentaci k datovým vazbám a kódováním klíč-hodnota.

Zobrazení kolekce nemá žádnou standardní integrovanou položku zobrazení kolekce (například osnovu nebo zobrazení tabulky), takže vývojář zodpovídá za návrh a implementaci zobrazení prototypu pomocí jiných ovládacích prvků AppKitu, jako jsou pole obrázků, textová pole, popisky atd. Toto zobrazení prototypu se použije k zobrazení a práci s každou položkou spravovanou zobrazením kolekce a uloží se do .xib souboru.

Vzhledem k tomu, že vývojář zodpovídá za vzhled a chování položky zobrazení kolekce, zobrazení kolekce nemá žádnou integrovanou podporu pro zvýraznění vybrané položky v mřížce. Implementace této funkce bude popsána v tomto článku.

Definování datového modelu

Před vytvořením datové vazby v Tvůrci rozhraní musí být v aplikaci Xamarin.Mac definována kompatibilní třída KVC (Key-Value Coding)/Key-Value Observing (KVO), aby fungovala jako datový model pro vazbu. Datový model poskytuje všechna data, která se zobrazí v kolekci, a přijímá veškeré úpravy dat, která uživatel provede v uživatelském rozhraní při spuštění aplikace.

Příklad aplikace, která spravuje skupinu zaměstnanců, je možné použít k definování datového modelu následující třídu:

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

Datový PersonModel model se použije ve zbývající části tohoto článku.

Práce se zobrazením kolekce

Datová vazba se zobrazením kolekce je velmi podobná vazbě se zobrazením tabulky, jak NSCollectionViewDataSource se používá k poskytování dat pro kolekci. Vzhledem k tomu, že zobrazení kolekce nemá přednastavený formát zobrazení, je potřeba více práce, aby bylo možné poskytnout zpětnou vazbu k interakci uživatelů a sledovat výběr uživatele.

Vytvoření prototypu buňky

Vzhledem k tomu, že zobrazení kolekce neobsahuje výchozí prototyp buňky, vývojář bude muset do aplikace Xamarin.Mac přidat jeden nebo více .xib souborů, aby definoval rozložení a obsah jednotlivých buněk.

Postupujte následovně:

  1. V Průzkumník řešení klikněte pravým tlačítkem na název projektu a vyberte Přidat>nový soubor...

  2. Vyberte Řadič zobrazení mac>, pojmenujte ho (například EmployeeItem v tomto příkladu) a kliknutím na tlačítko Nový vytvořte:

    Přidání nového kontroleru zobrazení

    Tím se přidá EmployeeItem.csEmployeeItemController.cs soubor a soubor EmployeeItemController.xib do řešení projektu.

  3. Poklikáním otevřete EmployeeItemController.xib soubor pro úpravy v Tvůrci rozhraní Xcode.

  4. Přidejte ovládací prvky NSBoxa NSImageView dva NSLabel ovládací prvky do zobrazení a rozložte je následujícím způsobem:

    Návrh rozložení prototypu buňky

  5. Otevřete Editor asistentů a vytvořte výstup pro NSBox buňku, aby bylo možné ho použít k označení stavu výběru buňky:

    Vystavení NSBoxu v výstupu

  6. Vraťte se do standardního editoru a vyberte zobrazení obrázku.

  7. V nástroji Kontrola vazby vyberte vlastníka souboru Bind To>File a zadejte cestuself.Person.Iconke klíči modelu:

    Vytvoření vazby ikony

  8. Vyberte první popisek a v inspektoru vazeb vyberte vlastníka souboru Bind To>a zadejte cestuself.Person.Nameke klíči modelu:

    Vytvoření vazby názvu

  9. Vyberte druhý popisek a v inspektoru vazeb vyberte vlastníka souboru Bind to>File a zadejte cestuself.Person.Occupationke klíči modelu:

    Vázání povolání

  10. Uložte změny do .xib souboru a vraťte se do sady Visual Studio, aby se změny synchronizovaly.

EmployeeItemController.cs Upravte soubor a udělejte ho takto:

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

Když se na tento kód podíváte podrobněji, třída zdědí z NSCollectionViewItem toho, aby fungovala jako prototyp buňky Zobrazení kolekce. Vlastnost Person zveřejňuje třídu, která byla použita k vytvoření vazby na zobrazení a popisky obrázku v Xcode. Toto je instance výše vytvořené instance PersonModel .

Vlastnost BackgroundColor je zástupcem NSBox ovládacího prvku FillColor , který se použije k zobrazení stavu výběru buňky. Přepsáním Selected vlastnosti NSCollectionViewItem, následující kód nastaví nebo vymaže tento stav výběru:

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

Vytvoření zdroje dat zobrazení kolekce

Zdroj dat zobrazení kolekce (NSCollectionViewDataSource) poskytuje všechna data pro zobrazení kolekce a vytvoří a naplní buňku zobrazení kolekce (pomocí prototypu .xib ) podle potřeby pro každou položku v kolekci.

Přidejte novou třídu projektu, zavolejte ji CollectionViewDataSource a udělejte ji takto:

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

Při podrobném pohledu na tento kód třída dědí a NSCollectionViewDataSource zveřejňuje seznam PersonModel instancí prostřednictvím své Data vlastnosti.

Vzhledem k tomu, že tato kolekce má pouze jednu část, kód přepíše metodu GetNumberOfSections a vždy vrátí 1. GetNumberofItems Metoda se navíc přepíše na ni vrátí počet položek v Data seznamu vlastností.

Metoda GetItem se volá vždy, když je požadována nová buňka a vypadá takto:

public override NSCollectionViewItem GetItem(NSCollectionView collectionView, NSIndexPath indexPath)
{
    var item = collectionView.MakeItem("EmployeeCell", indexPath) as EmployeeItemController;
    item.Person = Data[(int)indexPath.Item];

    return item;
}

Metoda MakeItem Zobrazení kolekce je volána k vytvoření nebo vrácení opakovaně použitelné instance EmployeeItemController a jeho Person vlastnost je nastavena na položku, která se zobrazí v požadované buňce.

Před EmployeeItemController použitím následujícího kódu musí být zaregistrovaný v kontroleru zobrazení kolekce:

EmployeeCollection.RegisterClassForItem(typeof(EmployeeItemController), "EmployeeCell");

Identifikátor (EmployeeCell) použitý ve MakeItem volání se musí shodovat s názvem kontroleru zobrazení, který byl registrován v zobrazení kolekce. Tento krok se podrobně probírá níže.

Zpracování výběru položky

Aby bylo možné zpracovat výběr a zrušení výběru položek v kolekci, NSCollectionViewDelegate bude vyžadováno. Vzhledem k tomu, že tento příklad bude používat předdefinovaný NSCollectionViewFlowLayout typ rozložení, bude vyžadována NSCollectionViewDelegateFlowLayout konkrétní verze tohoto delegáta.

Přidejte do projektu novou třídu, zavolejte ji CollectionViewDelegate a udělejte ji takto:

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

Tyto ItemsSelected metody ItemsDeselected jsou přepsány a slouží k nastavení nebo PersonSelected vymazání vlastnosti Kontroleru zobrazení, který zpracovává zobrazení kolekce, když uživatel vybere nebo zruší výběr položky. Zobrazí se podrobně níže.

Vytvoření zobrazení kolekce v Tvůrci rozhraní

Se všemi požadovanými podpůrnými částmi je možné hlavní scénář upravit a přidat do něj zobrazení kolekce.

Postupujte následovně:

  1. Poklikáním Main.Storyboard na soubor v Průzkumník řešení ho otevřete pro úpravy v Tvůrci rozhraní Xcode.

  2. Přetáhněte zobrazení kolekce do hlavního zobrazení a změňte jeho velikost tak, aby vyplnilo zobrazení:

    Přidání zobrazení kolekce do rozložení

  3. Když je vybrané zobrazení kolekce, připnete ho pomocí Editoru omezení do zobrazení při změně velikosti:

    Snímek obrazovky znázorňující přidání nových omezení

  4. Ujistěte se, že je na návrhové ploše vybrané zobrazení kolekce (a ne v zobrazení ohraničeného posuvníkunebo v zobrazení klipu, které ho obsahuje), přepněte do Editoru asistentů a vytvořte výstup pro zobrazení kolekce:

    Snímek obrazovky s editorem asistentů, kde můžete vytvořit zásuvku

  5. Uložte změny a vraťte se do sady Visual Studio, aby se synchronizovaly.

Spojování všech

Všechny podpůrné části byly nyní zavedeny s třídou, která bude fungovat jako datový model (PersonModel), byla přidána k poskytování dat, byla vytvořena pro NSCollectionViewDelegateFlowLayout zpracování výběru položek a NSCollectionView byla přidána do hlavní scénáře a vystavena jako výstup (EmployeeCollectionNSCollectionViewDataSource).

Posledním krokem je úprava kontroleru zobrazení, který obsahuje zobrazení kolekce, a spojení všech částí dohromady pro naplnění kolekce a zpracování výběru položky.

ViewController.cs Upravte soubor a udělejte ho takto:

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

Při podrobném pohledu na tento kód je definována Datasource vlastnost, která bude obsahovat instanci CollectionViewDataSource , která bude poskytovat data pro zobrazení kolekce. PersonSelected Vlastnost je definována pro uložení PersonModel představující aktuálně vybranou položku v zobrazení kolekce. Tato vlastnost také vyvolá SelectionChanged událost při změně výběru.

Třída ConfigureCollectionView slouží k registraci kontroleru zobrazení, který funguje jako prototyp buňky v zobrazení kolekce pomocí následujícího řádku:

EmployeeCollection.RegisterClassForItem(typeof(EmployeeItemController), "EmployeeCell");

Všimněte si, že identifikátor (EmployeeCell) použitý k registraci prototypu odpovídá identifikátoru volaného v GetItem metodě CollectionViewDataSource definované výše:

var item = collectionView.MakeItem("EmployeeCell", indexPath) as EmployeeItemController;
...

Kromě toho typ kontroleru zobrazení musí odpovídat názvu .xib souboru, který přesně definuje prototyp. V případě tohoto příkladu EmployeeItemController a EmployeeItemController.xib.

Skutečné rozložení položek v zobrazení kolekce je řízeno třídou Rozložení zobrazení kolekce a lze ji dynamicky změnit přiřazením nové instance vlastnosti CollectionViewLayout . Změna této vlastnosti aktualizuje vzhled zobrazení kolekce bez animace změny.

Apple dodává dva předdefinované typy rozložení pomocí zobrazení kolekce, které budou zpracovávat nejběžnější použití: NSCollectionViewFlowLayout a NSCollectionViewGridLayout. Pokud vývojář vyžadoval vlastní formát, například rozložení položek v kruhu, může vytvořit vlastní instanci NSCollectionViewLayout a přepsat požadované metody, aby dosáhl požadovaného efektu.

Tento příklad používá výchozí rozložení toku, takže vytvoří instanci NSCollectionViewFlowLayout třídy a nakonfiguruje ji následujícím způsobem:

var flowLayout = new NSCollectionViewFlowLayout()
{
    ItemSize = new CGSize(150, 150),
    SectionInset = new NSEdgeInsets(10, 10, 10, 20),
    MinimumInteritemSpacing = 10,
    MinimumLineSpacing = 10
};

Vlastnost ItemSize definuje velikost každé jednotlivé buňky v kolekci. Vlastnost SectionInset definuje sady z okraje kolekce, ve které budou buňky rozloženy. MinimumInteritemSpacing definuje minimální mezery mezi položkami a MinimumLineSpacing definuje minimální mezery mezi řádky v kolekci.

Rozložení je přiřazeno k zobrazení kolekce a je CollectionViewDelegate připojena k zpracování výběru položky:

// Setup collection view
EmployeeCollection.CollectionViewLayout = flowLayout;
EmployeeCollection.Delegate = new CollectionViewDelegate(this);

Metoda PopulateWithData vytvoří novou instanci objektu CollectionViewDataSource, naplní ho daty, připojí ho k zobrazení kolekce a zavolá metodu ReloadData pro zobrazení položek:

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 je přepsána a volá metody a PopulateWithData zobrazí ConfigureCollectionView konečné zobrazení kolekce uživateli:

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

    // Initialize Collection View
    ConfigureCollectionView();
    PopulateWithData();
}

Shrnutí

Tento článek se podrobně podíval na práci se zobrazeními kolekce v aplikaci Xamarin.Mac. Nejprve se podívala na zveřejnění třídy Objective-C C# pomocí kódování klíč-hodnota (KVC) a pozorování klíčové hodnoty (KVO). Dále ukázala, jak použít třídu kompatibilní s KVO a vytvořit vazbu dat na zobrazení kolekce v Tvůrci rozhraní Xcode. Nakonec ukázala, jak pracovat se zobrazeními kolekce v kódu jazyka C#.