Бөлісу құралы:


Представления коллекции в Xamarin.Mac

В этой статье описывается работа с представлениями коллекции в приложении Xamarin.Mac. Он охватывает создание и обслуживание представлений коллекций в Xcode и Interface Builder и программной работе с ними.

При работе с C# и .NET в приложении Xamarin.Mac разработчик имеет доступ к тем же элементам управления AppKit Collection View, в которые работает Objective-C разработчик и Xcode . Так как Xamarin.Mac интегрируется непосредственно с Xcode, разработчик использует построитель интерфейсов Xcode для создания и поддержания представлений коллекции.

Отображает NSCollectionView сетку подвидов, упорядоченных с помощью NSCollectionViewLayout. Каждое подвью в сетке представлено тем NSCollectionViewItem , что управляет загрузкой содержимого представления из .xib файла.

Пример запуска приложения

В этой статье рассматриваются основы работы с представлениями коллекции в приложении Xamarin.Mac. Настоятельно рекомендуется сначала ознакомиться со статьей Hello, Mac , в частности в разделах "Общие сведения о Xcode и конструкторе интерфейсов" и "Торговых точках" и "Действия ", поскольку рассматриваются основные понятия и методы, используемые в этой статье.

Вы можете ознакомиться с классами И методами C# вObjective-Cразделе документа Xamarin.Mac Internals, а также объяснить RegisterExport команды, используемые для подключения классов C# к Objective-C объектам и элементам пользовательского интерфейса.

Сведения о представлениях коллекции

Основная цель представления коллекции (NSCollectionView) заключается в визуальном расположении группы объектов в упорядоченном режиме с помощью макета представления коллекции (NSCollectionViewLayout), при этом каждый отдельный объект (NSCollectionViewItem) получает свое собственное представление в более крупной коллекции. Представления коллекции работают с помощью методов кодирования привязки данных и кодирования ключом и таким образом, прежде чем продолжить работу с этой статьей , ознакомьтесь с документацией по привязке данных и кодированию ключей.

Представление коллекции не имеет стандартного встроенного элемента представления коллекции (например, представления структуры или таблицы), поэтому разработчик отвечает за проектирование и реализацию представления прототипа с помощью других элементов управления AppKit, таких как поля изображения, текстовые поля, метки и т. д. Это представление прототипа будет использоваться для отображения и работы с каждым элементом, управляемым представлением коллекции и хранящимся в .xib файле.

Так как разработчик отвечает за внешний вид элемента представления коллекции, представление коллекции не поддерживает встроенную поддержку выделения выбранного элемента в сетке. Реализация этой функции будет описана в этой статье.

Определение модели данных

Прежде чем привязка данных к представлению коллекции в построителе интерфейсов, в приложении Xamarin.Mac должна быть определена соответствующая классу кодирование ключей (KVC)/Key-Value Observing (KVO) для привязки. Модель данных предоставляет все данные, которые будут отображаться в коллекции и получают любые изменения данных, которые пользователь делает в пользовательском интерфейсе при запуске приложения.

Рассмотрим пример приложения, которое управляет группой сотрудников, можно использовать следующий класс для определения модели данных:

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

Модель PersonModel данных будет использоваться в остальной части этой статьи.

Работа с представлением коллекции

Привязка данных с представлением коллекции очень похожа на привязку с табличным представлением, так как NSCollectionViewDataSource используется для предоставления данных для коллекции. Так как представление коллекции не имеет предустановленного формата отображения, для получения отзывов о взаимодействии с пользователем и отслеживания выбора пользователей требуется дополнительная работа.

Создание прототипа ячейки

Так как представление коллекции не включает прототип ячейки по умолчанию, разработчику потребуется добавить один или несколько .xib файлов в приложение Xamarin.Mac, чтобы определить макет и содержимое отдельных ячеек.

Выполните следующие действия.

  1. В Обозреватель решений щелкните правой кнопкой мыши имя проекта и выберите "Добавить>новый файл".

  2. Выберите контроллер Mac>View, присвойте ему имя (напримерEmployeeItem, в этом примере) и нажмите кнопку "Создать", чтобы создать:

    Добавление нового контроллера представления

    Это добавит EmployeeItem.csEmployeeItemController.cs файл и EmployeeItemController.xib файл в решение проекта.

  3. Дважды щелкните EmployeeItemController.xib файл, чтобы открыть его для редактирования в построителе интерфейсов Xcode.

  4. Добавьте элемент NSBoxNSImageView управления и два NSLabel элемента управления в представление и разложите их следующим образом:

    Проектирование макета прототипа ячейки

  5. Откройте редактор помощника и создайте выход для этого, чтобы его можно было использовать для NSBox указания состояния выделения ячейки:

    Предоставление NSBox в выходе

  6. Вернитесь в стандартный редактор и выберите представление изображения.

  7. В инспекторе привязки выберите "Привязка к>владельцу файла" и введите путьself.Person.Iconк ключу модели:

    Привязка значка

  8. Выберите первую метку и в инспекторе привязки выберите "Привязка к>владельцу файла" и введите путь self.Person.Name к ключу модели:

    Привязка имени

  9. Выберите вторую метку и в инспекторе привязки выберите "Привязка к>владельцу файла" и введите путь self.Person.Occupation ключа модели:

    Привязка оккупации

  10. Сохраните изменения .xib в файле и вернитесь в Visual Studio, чтобы синхронизировать изменения.

Измените EmployeeItemController.cs файл и сделайте его следующим образом:

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

Подробно рассмотрим этот код, класс наследует от NSCollectionViewItem него, поэтому он может выступать в качестве прототипа для ячейки представления коллекции. Свойство Person предоставляет класс, который использовался для привязки данных к представлению изображений и меткам в Xcode. Это экземпляр созданного PersonModel выше.

Свойство BackgroundColor — это ярлык NSBox элемента управления FillColor , который будет использоваться для отображения состояния выделения ячейки. Переопределив Selected свойство объекта NSCollectionViewItem, следующий код задает или очищает это состояние выбора:

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

Создание источника данных представления коллекции

Источник данных представления коллекции (NSCollectionViewDataSource) предоставляет все данные для представления коллекции и создает и заполняет ячейку представления коллекции (с помощью .xib прототипа) по мере необходимости для каждого элемента в коллекции.

Добавьте новый класс проекта, вызовите его и сделайте его CollectionViewDataSource следующим образом:

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

Подробные сведения об этом коде класс наследует от NSCollectionViewDataSource и предоставляет список экземпляров PersonModel через его Data свойство.

Так как эта коллекция содержит только один раздел, код переопределяет GetNumberOfSections метод и всегда возвращает 1. Кроме того, метод GetNumberofItems переопределяется при возврате количества элементов в списке Data свойств.

Метод GetItem вызывается всякий раз, когда требуется новая ячейка и выглядит следующим образом:

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 представления коллекции вызывается для создания или возврата повторно используемых экземпляров EmployeeItemController свойства, а его Person свойство — элемент, отображаемый в запрошенной ячейке.

Необходимо EmployeeItemController зарегистрировать в контроллере представления коллекции заранее с помощью следующего кода:

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

Идентификатор (EmployeeCell), используемый в вызовеMakeItem, должен соответствовать имени контроллера представления, зарегистрированного в представлении коллекции. Этот шаг подробно описан ниже.

Обработка выделения элементов

Для обработки выделения и отмены выбора элементов в коллекции NSCollectionViewDelegate потребуется. Так как в этом примере будет использоваться встроенный NSCollectionViewFlowLayout тип макета, NSCollectionViewDelegateFlowLayout потребуется определенная версия этого делегата.

Добавьте новый класс в проект, вызовите его CollectionViewDelegate и сделайте его следующим образом:

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

ItemsDeselected Методы ItemsSelected переопределяются и используются для задания или очистки PersonSelected свойства контроллера представления, обрабатывающего представление коллекции, когда пользователь выбирает или отменяет выбор элемента. Это будет подробно показано ниже.

Создание представления коллекции в построителе интерфейсов

При использовании всех необходимых вспомогательных частей основной раскадровки можно изменить и добавить в него представление коллекции.

Выполните следующие действия.

  1. Дважды щелкните Main.Storyboard файл в Обозреватель решений, чтобы открыть его для редактирования в построителе интерфейсов Xcode.

  2. Перетащите представление коллекции в основное представление и измените его размер, чтобы заполнить представление:

    Добавление представления коллекции в макет

  3. Выбрав представление коллекции, используйте редактор ограничений, чтобы закрепить его в представлении при изменении размера:

    Снимок экрана: добавление новых ограничений.

  4. Убедитесь, что представление коллекции выбрано в области конструктора (а не в режиме обрамленной прокрутки или в режиме клипа), перейдите в редактор помощника и создайте выход для представления коллекции:

    Снимок экрана: редактор помощника, где можно создать выход.

  5. Сохраните изменения и вернитесь в Visual Studio для синхронизации.

Объединение всего этого вместе

Теперь все вспомогательные части были помещены на место с классом, который будет выступать в качестве модели данных (PersonModel), NSCollectionViewDataSource добавлен для предоставления данных, NSCollectionViewDelegateFlowLayout был создан для обработки выбора элементов и NSCollectionView добавлен в основной раскадровки и представлен как выход (EmployeeCollection).

Последним шагом является изменение контроллера представления, содержащего представление коллекции, и объединение всех частей для заполнения коллекции и обработки выбора элементов.

Измените ViewController.cs файл и сделайте его следующим образом:

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

Подробно рассмотрим этот код, Datasource свойство определяется для хранения экземпляра CollectionViewDataSource , который будет предоставлять данные для представления коллекции. Свойство PersonSelected определяется для хранения PersonModel представления выбранного элемента в представлении коллекции. Это свойство также вызывает SelectionChanged событие при изменении выделения.

Класс ConfigureCollectionView используется для регистрации контроллера представления, который выступает в качестве прототипа ячейки в представлении коллекции, используя следующую строку:

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

Обратите внимание, что идентификатор (EmployeeCell), используемый для регистрации прототипа, соответствует одному из указанных CollectionViewDataSourceGetItem выше методов:

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

Кроме того, тип контроллера представления должен соответствовать имени .xib файла, который определяет прототип точно. В этом примере EmployeeItemController и EmployeeItemController.xib.

Фактический макет элементов в представлении коллекции управляется классом макета представления коллекции и может быть динамически изменен во время выполнения, назначив новый экземпляр свойству CollectionViewLayout . Изменение этого свойства обновляет внешний вид представления коллекции без анимации изменения.

Apple поставляет два встроенных типа макетов с представлением коллекции, который будет обрабатывать наиболее типичные варианты использования: NSCollectionViewFlowLayout и NSCollectionViewGridLayout. Если разработчику требуется настраиваемый формат, такой как добавление элементов в круг, он может создать настраиваемый экземпляр NSCollectionViewLayout и переопределить необходимые методы для достижения желаемого эффекта.

В этом примере используется макет потока по умолчанию, поэтому он создает экземпляр NSCollectionViewFlowLayout класса и настраивает его следующим образом:

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

Свойство ItemSize определяет размер каждой отдельной ячейки в коллекции. Свойство SectionInset определяет наборы из края коллекции, в которую будут размещены ячейки. MinimumInteritemSpacing определяет минимальный интервал между элементами и MinimumLineSpacing определяет минимальный интервал между строками в коллекции.

Макет назначается представлению коллекции, а экземпляр CollectionViewDelegate присоединен к выбору элемента:

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

Метод PopulateWithData создает новый экземпляр CollectionViewDataSourceобъекта, заполняет его данными, присоединяет его к представлению коллекции и вызывает ReloadData метод для отображения элементов:

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

Метод ViewDidLoad переопределяется и вызывает ConfigureCollectionViewPopulateWithData методы для отображения окончательного представления коллекции пользователю:

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

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

Итоги

В этой статье подробно рассматривается работа с представлениями коллекции в приложении Xamarin.Mac. Во-первых, он рассмотрел представление класса Objective-C C# с помощью кода ключевого значения (KVC) и наблюдения за ключом (KVO). Далее он показал, как использовать класс, совместимый с KVO, и Привязка данных к представлениям коллекции в построителе интерфейсов Xcode. Наконец, он показал, как взаимодействовать с представлениями коллекции в коде C#.