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

В этой статье рассматривается проектирование и работа с контроллерами представлений таблиц и табличных представлений в приложении Xamarin.tvOS.

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

Представления таблиц обычно отображаются в одной стороне разделенного представления в виде навигации, с подробными сведениями выбранного элемента, отображаемого в противоположной стороне:

Пример представления таблицы

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

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

Выбранный элемент

Apple предлагает следующие рекомендации по работе с таблицами:

  • Помните о ширине . Попробуйте нанести правильный баланс в ширину таблицы. Если таблица слишком широка, это может быть трудно проверить с расстояния и может отнять доступную область содержимого. Если таблица слишком узкая, это может привести к усечению или обтекание информации, опять же это может быть трудно для пользователя читать из комнаты.
  • Отображение оглавлений быстро — для больших списков данных, отложенной загрузки содержимого и начала отображения сведений сразу после представления таблицы пользователю. Если таблица занимает много времени для загрузки, пользователь может потерять интерес к вашему приложению или подумать, что она заблокирована.
  • Сообщите пользователю о длительных нагрузках содержимого. Если время загрузки длинной таблицы неизбежна, примените индикатор хода выполнения или индикатор действия, чтобы они знали, что приложение не заблокировано.

Типы ячеек представления таблицы

A UITableViewCell используется для представления отдельных строк данных в представлении таблицы. Apple определила несколько типов ячеек таблицы по умолчанию:

  • По умолчанию этот тип представляет параметр Image в левой части ячейки и выровненного по левому краю заголовка справа.
  • Подзаголовок — этот тип представляет выровненный по левому краю заголовок в первой строке и меньшее выровненное по левому краю подзаголовок на следующей строке.
  • Значение 1 . Этот тип представляет левый выровненный заголовок с более светлым цветом, выровненным по правому краю подзаголовок в той же строке.
  • Значение 2 . Этот тип представляет правый выровненный заголовок с более светлым цветом, выровненным по левому краю подзаголовок в той же строке.

Все типы ячеек представления таблиц по умолчанию также поддерживают графические элементы, такие как индикаторы раскрытия или флажки.

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

Apple предлагает следующие рекомендации по работе с ячейками представления таблиц:

  • Избегайте вырезки текста. Сохраните отдельные строки текста короткими, чтобы они не усечены. Усеченные слова или фразы трудно проанализировать с пользователя по всей комнате.
  • Рассмотрим состояние фокусируемой строки. Так как строка становится больше, с более округленными углами при фокусе, необходимо проверить внешний вид ячейки во всех состояниях. Изображения или текст могут быть обрезаны или выглядеть неправильно в состоянии "Фокус".
  • Используйте редактируемые таблицы с разреженным образом. Перемещение или удаление строк таблиц занимает больше времени, чем в iOS. Необходимо тщательно решить, будет ли эта функция добавлять или отвлекать вас от вашего приложения tvOS.
  • Создайте пользовательские типы ячеек, где это необходимо . Хотя встроенные типы ячеек таблицы отлично подходят для многих ситуаций, рекомендуется создавать пользовательские типы ячеек для нестандартной информации, чтобы обеспечить больший контроль и лучше представить информацию пользователю.

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

Самый простой способ работы с представлениями таблиц в приложении Xamarin.tvOS — создать и изменить внешний вид в конструкторе интерфейсов.

Чтобы начать работу, выполните следующие действия:

  1. В Visual Studio для Mac запустите новый проект приложения tvOS и выберите одно представление приложения> tvOS>и нажмите кнопку "Далее".

    Выбор приложения с одним представлением

  2. Введите имя приложения и нажмите кнопку "Далее":

    Введите имя приложения

  3. Измените имя проекта и имя решения или примите значения по умолчанию и нажмите кнопку "Создать", чтобы создать новое решение:

    Имя проекта и имя решения

  4. На панели решений дважды щелкните Main.storyboard файл, чтобы открыть его в конструкторе iOS:

    Файл Main.storyboard

  5. Выберите и удалите контроллер представления по умолчанию:

    Выбор и удаление контроллера представления по умолчанию

  6. Выберите контроллер разделенного представления на панели элементов и перетащите его на поверхность конструктора.

  7. По умолчанию вы получите разделенное представление с контроллером представления навигации и контроллером представления таблицы в левой части и контроллером представления в правой части. Это рекомендуемое использование представления таблиц Apple в tvOS:

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

  8. Вам потребуется выбрать каждую часть представления таблицы и назначить ему пользовательское имя класса на вкладке "Мини-приложение" Обозреватель свойств, чтобы получить к нему доступ позже в коде C#. Например, контроллер представления таблицы:

    Назначение имени класса

  9. Убедитесь, что вы создаете пользовательский класс для контроллера представления таблицы, представления таблицы и любых ячеек прототипа. Visual Studio для Mac добавит пользовательские классы в дерево проекта по мере их создания:

    Пользовательские классы в дереве проекта

  10. Затем выберите представление таблицы в области конструктора и измените его свойства по мере необходимости. Например, количество ячеек прототипа и стиль (обычный или сгруппированные):

    Вкладка мини-приложения

  11. Для каждой ячейки прототипа выберите ее и назначьте уникальный идентификатор на вкладке "Мини-приложение" Обозреватель свойств. Этот шаг очень важен, так как вам потребуется этот идентификатор позже при заполнении таблицы. Пример: AttrCell

    Вкладка мини-приложения

  12. Вы также можете выбрать, чтобы представить ячейку в качестве одного из типов ячеек представления таблицы по умолчанию с помощью раскрывающегося списка "Стиль " или задать для него настраиваемый и использовать область конструктора для макета ячейки путем перетаскивания других мини-приложений пользовательского интерфейса из панели элементов:

    Макет ячейки

  13. Назначьте уникальное имя каждому элементу пользовательского интерфейса в конструкторе "Ячейка прототипа" на вкладке "Мини-приложение" Обозреватель, чтобы получить доступ к ним позже в коде C#:

    Присвоение имени

  14. Повторите приведенный выше шаг для всех ячеек прототипа в представлении таблицы.

  15. Затем назначьте пользовательские классы остальным элементам пользовательского интерфейса, макетируйте представление сведений и назначьте уникальные имена каждому элементу пользовательского интерфейса в представлении "Сведения", чтобы получить доступ к ним в C#. Пример:

    Макет пользовательского интерфейса

  16. Сохраните изменения в раскадровке.

Проектирование модели данных

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

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

Чтобы создать модель данных для привлечения, щелкните правой кнопкой мыши имя проекта на панели решения и выберите команду Добавить>новый файл.... Введите AttractionInformation имя и нажмите кнопку "Создать":

Ввод AttractionInformation для имени

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

using System;
using Foundation;

namespace tvTable
{
    public class AttractionInformation : NSObject
    {
        #region Computed Properties
        public CityInformation City { get; set;}
        public string Name { get; set;}
        public string Description { get; set;}
        public string ImageName { get; set;}
        public bool IsFavorite { get; set;}
        public bool AddDirections { get; set;}
        #endregion

        #region Constructors
        public AttractionInformation (string name, string description, string imageName)
        {
            // Initialize
            this.Name = name;
            this.Description = description;
            this.ImageName = imageName;
        }
        #endregion
    }
}

Этот класс предоставляет свойства для хранения сведений об заданной достопримечательностью.

Затем снова щелкните правой кнопкой мыши имя проекта на панели решения и выберите "Добавить>новый файл".... Введите CityInformation имя и нажмите кнопку "Создать":

Ввод CityInformation для имени

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

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

namespace tvTable
{
    public class CityInformation : NSObject
    {
        #region Computed Properties
        public string Name { get; set; }
        public List<AttractionInformation> Attractions { get; set;}
        public bool FlightBooked { get; set;}
        #endregion

        #region Constructors
        public CityInformation (string name)
        {
            // Initialize
            this.Name = name;
            this.Attractions = new List<AttractionInformation> ();
        }
        #endregion

        #region Public Methods
        public void AddAttraction (AttractionInformation attraction)
        {
            // Mark as belonging to this city
            attraction.City = this;

            // Add to collection
            Attractions.Add (attraction);
        }

        public void AddAttraction (string name, string description, string imageName)
        {
            // Create attraction
            var attraction = new AttractionInformation (name, description, imageName);

            // Mark as belonging to this city
            attraction.City = this;

            // Add to collection
            Attractions.Add (attraction);
        }
        #endregion
    }
}

Этот класс содержит все сведения о целевом городе, коллекции достопримечательностей для этого города и предоставляет два вспомогательных метода (AddAttraction), чтобы упростить добавление достопримечательностей в город.

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

Для каждого представления таблицы требуется источник данных (UITableViewDataSource) для предоставления данных для таблицы и создания необходимых строк в соответствии с представлением таблицы.

В приведенном выше примере щелкните правой кнопкой мыши имя проекта в Обозреватель решений, выберите "Добавить>новый файл" и вызовите его AttractionTableDatasource и нажмите кнопку "Создать" для создания. Затем измените AttractionTableDatasource.cs файл и сделайте его следующим образом:

using System;
using System.Collections.Generic;
using UIKit;

namespace tvTable
{
    public class AttractionTableDatasource : UITableViewDataSource
    {
        #region Constants
        const string CellID = "AttrCell";
        #endregion

        #region Computed Properties
        public AttractionTableViewController Controller { get; set;}
        public List<CityInformation> Cities { get; set;}
        #endregion

        #region Constructors
        public AttractionTableDatasource (AttractionTableViewController controller)
        {
            // Initialize
            this.Controller = controller;
            this.Cities = new List<CityInformation> ();
            PopulateCities ();
        }
        #endregion

        #region Public Methods
        public void PopulateCities ()
        {
            // Clear existing
            Cities.Clear ();

            // Define cities and attractions
            var Paris = new CityInformation ("Paris");
            Paris.AddAttraction ("Eiffel Tower", "Is a wrought iron lattice tower on the Champ de Mars in Paris, France.", "EiffelTower");
            Paris.AddAttraction ("Musée du Louvre", "is one of the world's largest museums and a historic monument in Paris, France.", "Louvre");
            Paris.AddAttraction ("Moulin Rouge", "French for 'Red Mill', is a cabaret in Paris, France.", "MoulinRouge");
            Paris.AddAttraction ("La Seine", "Is a 777-kilometre long river and an important commercial waterway within the Paris Basin.", "RiverSeine");
            Cities.Add (Paris);

            var SanFran = new CityInformation ("San Francisco");
            SanFran.AddAttraction ("Alcatraz Island", "Is located in the San Francisco Bay, 1.25 miles (2.01 km) offshore from San Francisco.", "Alcatraz");
            SanFran.AddAttraction ("Golden Gate Bridge", "Is a suspension bridge spanning the Golden Gate strait between San Francisco Bay and the Pacific Ocean", "GoldenGateBridge");
            SanFran.AddAttraction ("San Francisco", "Is the cultural, commercial, and financial center of Northern California.", "SanFrancisco");
            SanFran.AddAttraction ("Telegraph Hill", "Is primarily a residential area, much quieter than adjoining North Beach.", "TelegraphHill");
            Cities.Add (SanFran);

            var Houston = new CityInformation ("Houston");
            Houston.AddAttraction ("City Hall", "It was constructed in 1938-1939, and is located in Downtown Houston.", "CityHall");
            Houston.AddAttraction ("Houston", "Is the most populous city in Texas and the fourth most populous city in the US.", "Houston");
            Houston.AddAttraction ("Texas Longhorn", "Is a breed of cattle known for its characteristic horns, which can extend to over 6 ft.", "LonghornCattle");
            Houston.AddAttraction ("Saturn V Rocket", "was an American human-rated expendable rocket used by NASA between 1966 and 1973.", "Rocket");
            Cities.Add (Houston);
        }
        #endregion

        #region Override Methods
        public override UITableViewCell GetCell (UITableView tableView, Foundation.NSIndexPath indexPath)
        {
            // Get cell
            var cell = tableView.DequeueReusableCell (CellID) as AttractionTableCell;

            // Populate cell
            cell.Attraction = Cities [indexPath.Section].Attractions [indexPath.Row];

            // Return new cell
            return cell;
        }

        public override nint NumberOfSections (UITableView tableView)
        {
            // Return number of cities
            return Cities.Count;
        }

        public override nint RowsInSection (UITableView tableView, nint section)
        {
            // Return the number of attractions in the given city
            return Cities [(int)section].Attractions.Count;
        }

        public override string TitleForHeader (UITableView tableView, nint section)
        {
            // Get the name of the current city
            return Cities [(int)section].Name;
        }
        #endregion
    }
}

Давайте рассмотрим несколько разделов класса подробно.

Во-первых, мы определили константу для хранения уникального идентификатора ячейки прототипа (это тот же идентификатор, назначенный в конструкторе интерфейсов выше), добавил ярлык обратно в контроллер представления таблиц и создал хранилище для наших данных:

const string CellID = "AttrCell";
public AttractionTableViewController Controller { get; set;}
public List<CityInformation> Cities { get; set;}

Затем мы сохраняем контроллер представления таблиц, а затем создадим и заполните наш источник данных (с помощью моделей данных, определенных выше) при создании класса:

public AttractionTableDatasource (AttractionTableViewController controller)
{
    // Initialize
    this.Controller = controller;
    this.Cities = new List<CityInformation> ();
    PopulateCities ();
}

В качестве примера метод просто создает объекты модели данных в памяти, PopulateCities однако их можно легко считывать из базы данных или веб-службы в реальном приложении:

public void PopulateCities ()
{
    // Clear existing
    Cities.Clear ();

    // Define cities and attractions
    var Paris = new CityInformation ("Paris");
    Paris.AddAttraction ("Eiffel Tower", "Is a wrought iron lattice tower on the Champ de Mars in Paris, France.", "EiffelTower");
    ...
}

Метод NumberOfSections возвращает количество разделов в таблице:

public override nint NumberOfSections (UITableView tableView)
{
    // Return number of cities
    return Cities.Count;
}

Для представлений таблиц с простым стилем всегда возвращается значение 1.

Метод RowsInSection возвращает количество строк в текущем разделе:

public override nint RowsInSection (UITableView tableView, nint section)
{
    // Return the number of attractions in the given city
    return Cities [(int)section].Attractions.Count;
}

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

Метод TitleForHeader возвращает заголовок для данного раздела:

public override string TitleForHeader (UITableView tableView, nint section)
{
    // Get the name of the current city
    return Cities [(int)section].Name;
}

Для типа обычного табличного представления оставьте заголовок пустым ("").

Наконец, при запросе представления таблицы создайте и заполните ячейку прототипа GetCell с помощью метода:

public override UITableViewCell GetCell (UITableView tableView, Foundation.NSIndexPath indexPath)
{
    // Get cell
    var cell = tableView.DequeueReusableCell (CellID) as AttractionTableCell;

    // Populate cell
    cell.Attraction = Cities [indexPath.Section].Attractions [indexPath.Row];

    // Return new cell
    return cell;
}

Дополнительные сведения о работе с приложением UITableViewDatasourceСм. в документации Apple UITableViewDatasource .

Делегат представления таблицы

Для каждого представления таблицы требуется делегат (UITableViewDelegate) реагировать на взаимодействие пользователя или другие системные события таблицы.

В приведенном выше примере щелкните правой кнопкой мыши имя проекта в Обозреватель решений, выберите "Добавить>новый файл" и вызовите его AttractionTableDelegate и нажмите кнопку "Создать" для создания. Затем измените AttractionTableDelegate.cs файл и сделайте его следующим образом:

using System;
using System.Collections.Generic;
using UIKit;

namespace tvTable
{
    public class AttractionTableDelegate : UITableViewDelegate
    {
        #region Computed Properties
        public AttractionTableViewController Controller { get; set;}
        #endregion

        #region Constructors
        public AttractionTableDelegate (AttractionTableViewController controller)
        {
            // Initializw
            this.Controller = controller;
        }
        #endregion

        #region Override Methods
        public override void RowSelected (UITableView tableView, Foundation.NSIndexPath indexPath)
        {
            var attraction = Controller.Datasource.Cities [indexPath.Section].Attractions [indexPath.Row];
            attraction.IsFavorite = (!attraction.IsFavorite);

            // Update UI
            Controller.TableView.ReloadData ();
        }

        public override bool CanFocusRow (UITableView tableView, Foundation.NSIndexPath indexPath)
        {
            // Inform caller of highlight change
            RaiseAttractionHighlighted (Controller.Datasource.Cities [indexPath.Section].Attractions [indexPath.Row]);
            return true;
        }
        #endregion

        #region Events
        public delegate void AttractionHighlightedDelegate (AttractionInformation attraction);
        public event AttractionHighlightedDelegate AttractionHighlighted;

        internal void RaiseAttractionHighlighted (AttractionInformation attraction)
        {
            // Inform caller
            if (this.AttractionHighlighted != null) this.AttractionHighlighted (attraction);
        }
        #endregion
    }
}

Давайте рассмотрим несколько разделов этого класса подробно.

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

public AttractionTableViewController Controller { get; set;}
...

public AttractionTableDelegate (AttractionTableViewController controller)
{
    // Initialize
    this.Controller = controller;
}

Затем при выборе строки (пользователь щелкает сенсорный поверхность Apple Remote) мы хотим пометить достопримечательность , представленную выбранной строкой в качестве избранного:

public override void RowSelected (UITableView tableView, Foundation.NSIndexPath indexPath)
{
    var attraction = Controller.Datasource.Cities [indexPath.Section].Attractions [indexPath.Row];
    attraction.IsFavorite = (!attraction.IsFavorite);

    // Update UI
    Controller.TableView.ReloadData ();
}

Затем, когда пользователь выделяет строку (предоставляя фокус с помощью Apple Remote Touch Surface) мы хотим представить сведения о привлекательности, представленной этой строкой в разделе "Сведения" нашего контроллера разделенного представления:

public override bool CanFocusRow (UITableView tableView, Foundation.NSIndexPath indexPath)
{
    // Inform caller of highlight change
    RaiseAttractionHighlighted (Controller.Datasource.Cities [indexPath.Section].Attractions [indexPath.Row]);
    return true;
}
...

public delegate void AttractionHighlightedDelegate (AttractionInformation attraction);
public event AttractionHighlightedDelegate AttractionHighlighted;

internal void RaiseAttractionHighlighted (AttractionInformation attraction)
{
    // Inform caller
    if (this.AttractionHighlighted != null) this.AttractionHighlighted (attraction);
}

Метод CanFocusRow вызывается для каждой строки, которая будет получать фокус в представлении таблицы. Возвращается true , если строка может получить фокус, в противном случае возвращается false. В этом примере мы создали настраиваемое AttractionHighlighted событие, которое будет создано для каждой строки по мере получения фокуса.

Дополнительные сведения о работе с приложением UITableViewDelegateСм. в документации Apple UITableViewDelegate .

Ячейка представления таблицы

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

В примере приложения дважды щелкните AttractionTableCell.cs файл, чтобы открыть его для редактирования, и сделайте его следующим образом:

using System;
using Foundation;
using UIKit;

namespace tvTable
{
    public partial class AttractionTableCell : UITableViewCell
    {
        #region Private Variables
        private AttractionInformation _attraction = null;
        #endregion

        #region Computed Properties
        public AttractionInformation Attraction {
            get { return _attraction; }
            set {
                _attraction = value;
                UpdateUI ();
            }
        }
        #endregion

        #region Constructors
        public AttractionTableCell (IntPtr handle) : base (handle)
        {
        }
        #endregion

        #region Private Methods
        private void UpdateUI ()
        {
            // Trap all errors
            try {
                Title.Text = Attraction.Name;
                Favorite.Hidden = (!Attraction.IsFavorite);
            } catch {
                // Since the UI might not be fully loaded, ignore
                // all errors at this point
            }
        }
        #endregion
    }
}

Этот класс предоставляет хранилище для объекта Модели данных Достопримечательность (AttractionInformation как определено выше), отображаемого в заданной строке:

private AttractionInformation _attraction = null;
...

public AttractionInformation Attraction {
    get { return _attraction; }
    set {
        _attraction = value;
        UpdateUI ();
    }
}

Метод UpdateUI заполняет мини-приложения пользовательского интерфейса (которые были добавлены в прототип ячейки в конструкторе интерфейсов) по мере необходимости:

private void UpdateUI ()
{
    // Trap all errors
    try {
        Title.Text = Attraction.Name;
        Favorite.Hidden = (!Attraction.IsFavorite);
    } catch {
        // Since the UI might not be fully loaded, ignore
        // all errors at this point
    }
}

Дополнительные сведения о работе с приложением UITableViewCellСм. в документации Apple UITableViewCell .

Контроллер представления таблицы

Контроллер представления таблицы (UITableViewController) управляет представлением таблицы, добавленным в раскадровку с помощью конструктора интерфейсов.

В примере приложения дважды щелкните AttractionTableViewController.cs файл, чтобы открыть его для редактирования, и сделайте его следующим образом:

using System;
using Foundation;
using UIKit;

namespace tvTable
{
    public partial class AttractionTableViewController : UITableViewController
    {
        #region Computed Properties
        public AttractionTableDatasource Datasource {
            get { return TableView.DataSource as AttractionTableDatasource; }
        }

        public AttractionTableDelegate TableDelegate {
            get { return TableView.Delegate as AttractionTableDelegate; }
        }
        #endregion

        #region Constructors
        public AttractionTableViewController (IntPtr handle) : base (handle)
        {
        }
        #endregion

        #region Override Methods
        public override void ViewDidLoad ()
        {
            base.ViewDidLoad ();

            // Setup table
            TableView.DataSource = new AttractionTableDatasource (this);
            TableView.Delegate = new AttractionTableDelegate (this);
            TableView.ReloadData ();
        }
        #endregion
    }
}

Давайте рассмотрим этот класс более подробно. Во-первых, мы создали ярлыки, чтобы упростить доступ к представлению DataSource таблиц и TableDelegate. Мы будем использовать их позже для обмена данными между представлением таблицы в левой части разделенного представления и представлением сведений справа.

Наконец, когда представление таблицы загружается в память, мы создадим экземпляры AttractionTableDatasource и AttractionTableDelegate (как созданные выше), так и присоединяем их к представлению таблицы.

Дополнительные сведения о работе с приложением UITableViewControllerСм. в документации Apple UITableViewController .

Потянув все вместе

Как указано в начале этого документа, представления таблиц обычно отображаются в одной стороне разделенного представления в виде навигации, с подробными сведениями выбранного элемента, отображаемого в противоположной стороне. Например:

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

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

Представление сведений

Например, приведенное выше в приложении для путешествий, для стандартного контроллера представления, представленного в правой части представления в качестве представления сведений, определяется настраиваемый класс (AttractionViewController).

using System;
using Foundation;
using UIKit;

namespace tvTable
{
    public partial class AttractionViewController : UIViewController
    {
        #region Private Variables
        private AttractionInformation _attraction = null;
        #endregion

        #region Computed Properties
        public AttractionInformation Attraction {
            get { return _attraction; }
            set {
                _attraction = value;
                UpdateUI ();
            }
        }

        public MasterSplitView SplitView { get; set;}
        #endregion

        #region Constructors
        public AttractionViewController (IntPtr handle) : base (handle)
        {
        }
        #endregion

        #region Public Methods
        public void UpdateUI ()
        {
            // Trap all errors
            try {
                City.Text = Attraction.City.Name;
                Title.Text = Attraction.Name;
                SubTitle.Text = Attraction.Description;

                IsFlighBooked.Hidden = (!Attraction.City.FlightBooked);
                IsFavorite.Hidden = (!Attraction.IsFavorite);
                IsDirections.Hidden = (!Attraction.AddDirections);
                BackgroundImage.Image = UIImage.FromBundle (Attraction.ImageName);
                AttractionImage.Image = BackgroundImage.Image;
            } catch {
                // Since the UI might not be fully loaded, ignore
                // all errors at this point
            }
        }
        #endregion

        #region Override Methods
        public override void ViewWillAppear (bool animated)
        {
            base.ViewWillAppear (animated);

            // Ensure the UI Updates
            UpdateUI ();
        }
        #endregion

        #region Actions
        partial void BookFlight (NSObject sender)
        {
            // Ask user to book flight
            AlertViewController.PresentOKCancelAlert ("Book Flight",
                                                      string.Format ("Would you like to book a flight to {0}?", Attraction.City.Name),
                                                      this,
                                                      (ok) => {
                Attraction.City.FlightBooked = ok;
                IsFlighBooked.Hidden = (!Attraction.City.FlightBooked);
            });
        }

        partial void GetDirections (NSObject sender)
        {
            // Ask user to add directions
            AlertViewController.PresentOKCancelAlert ("Add Directions",
                                                     string.Format ("Would you like to add directions to {0} to you itinerary?", Attraction.Name),
                                                     this,
                                                     (ok) => {
                                                         Attraction.AddDirections = ok;
                                                         IsDirections.Hidden = (!Attraction.AddDirections);
                                                     });
        }

        partial void MarkFavorite (NSObject sender)
        {
            // Flip favorite state
            Attraction.IsFavorite = (!Attraction.IsFavorite);
            IsFavorite.Hidden = (!Attraction.IsFavorite);

            // Reload table
            SplitView.Master.TableController.TableView.ReloadData ();
        }
        #endregion
    }
}

Здесь мы предоставили свойство "Достопримечательность " (AttractionInformation) и создали UpdateUI метод, заполняющий мини-приложения пользовательского интерфейса, добавленные в представление в конструкторе интерфейсов.

Мы также определили ярлык обратно в контроллер разделенного представления (SplitView), который мы будем использовать для обмена данными об изменениях в представлении таблицы (AcctractionTableView).

Наконец, пользовательские действия (события) были добавлены в три UIButton экземпляра, созданные в конструкторе интерфейсов, которые позволяют пользователю пометить достопримечательность как избранное, получить направления в достопримечательность и забронировать рейс в данный город.

Контроллер представления навигации

Так как контроллер представления таблицы вложен в контроллер представления навигации в левой части разделенного представления, контроллер представления навигации был назначен настраиваемый класс (MasterNavigationController) в конструкторе интерфейсов и определен следующим образом:

using System;
using Foundation;
using UIKit;

namespace tvTable
{
    public partial class MasterNavigationController : UINavigationController
    {
        #region Computed Properties
        public MasterSplitView SplitView { get; set;}
        public AttractionTableViewController TableController {
            get { return TopViewController as AttractionTableViewController; }
        }
        #endregion

        #region Constructors
        public MasterNavigationController (IntPtr handle) : base (handle)
        {
        }
        #endregion
    }
}

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

  • SplitView — ссылка на контроллер разделенного представления (MainSpiltViewController), к которому принадлежит контроллер представления навигации.
  • TableController — Получает контроллер представления таблицы (AttractionTableViewController), представленный в качестве верхнего представления в контроллере представления навигации.

Контроллер разделенного представления

Так как контроллер разделенного представления является основой нашего приложения, мы создали для него пользовательский класс (MasterSplitViewController) в конструкторе интерфейсов и определили его следующим образом:

using System;
using Foundation;
using UIKit;

namespace tvTable
{
    public partial class MasterSplitView : UISplitViewController
    {
        #region Computed Properties
        public AttractionViewController Details {
            get { return ViewControllers [1] as AttractionViewController; }
        }

        public MasterNavigationController Master {
            get { return ViewControllers [0] as MasterNavigationController; }
        }
        #endregion

        #region Constructors
        public MasterSplitView (IntPtr handle) : base (handle)
        {
        }
        #endregion

        #region Override Methods
        public override void ViewDidLoad ()
        {
            base.ViewDidLoad ();

            // Initialize
            Master.SplitView = this;
            Details.SplitView = this;

            // Wire-up events
            Master.TableController.TableDelegate.AttractionHighlighted += (attraction) => {
                // Display new attraction
                Details.Attraction = attraction;
            };
        }
        #endregion
    }
}

Во-первых, мы создадим ярлыки на стороне сведений в разделенном представлении (AttractionViewController) и на главной стороне (MasterNavigationController). Опять же, это упрощает обмен данными между двумя сторонами позже.

Затем, когда разделенное представление загружается в память, мы прикрепляем контроллер разделенного представления к обеим сторонам разделенного представления и реагируем на то, что пользователь выделяет достопримечательность в представлении таблицы (AttractionHighlighted) путем отображения нового достопримечательности в стороне сведений в режиме разделения.

Подробные представления таблиц

Так как tvOS основан на iOS, представления таблиц и контроллеры представления таблиц разработаны и ведут себя аналогично. Дополнительные сведения о работе с представлением таблиц в приложении Xamarin см. в документации по iOS , работающей с таблицами и ячейками .

Итоги

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