Windows в Xamarin.Mac

В этой статье рассматривается работа с окнами и панелями в приложении Xamarin.Mac. В ней описывается создание окон и панелей в Xcode и Конструкторе интерфейсов, загрузка их из раскадровки и XIB-файлов и работа с ними программным способом.

При работе с C# и .NET в приложении Xamarin.Mac у вас есть доступ к тем же windows и панелям, в которые работает Objective-C разработчик и Xcode . Так как Xamarin.Mac интегрируется непосредственно с Xcode, с помощью конструктора интерфейсов Xcode можно создавать и поддерживать windows и панели (или при необходимости создавать их непосредственно в коде C#).

В зависимости от своей цели приложение Xamarin.Mac может представить одну или несколько Windows на экране для управления и координации информации, с которыми она отображается и с которыми работает. Основные функции окна:

  1. Чтобы предоставить область, в которой можно разместить и управлять представлениями и элементами управления.
  2. Чтобы принять и реагировать на события в ответ на взаимодействие пользователя с клавиатурой и мышью.

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

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

Editing a window in Xcode

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

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

Общие сведения о окнах

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

Согласно Apple, существует пять основных типов Windows в приложении macOS:

  • Окно документа — окно документа содержит данные пользователя на основе файлов, такие как электронная таблица или текстовый документ.
  • Окно приложения — это главное окно приложения, которое не основано на документе (например, приложение "Календарь" на Mac).
  • Панель — панель плавает над другими окнами и предоставляет средства или элементы управления, с которыми пользователи могут работать при открытии документов. В некоторых случаях панель может быть полупрозрачной (например, при работе с большой графикой).
  • Диалоговое окно — диалоговое окно отображается в ответ на действие пользователя и обычно предоставляет способы выполнения действия пользователями. Для закрытия диалогового окна требуется ответ от пользователя. (См. раздел Работа с диалогами)
  • Оповещения — это специальный тип диалогового окна, который отображается при возникновении серьезной проблемы (например, ошибки) или в качестве предупреждения (например, подготовки к удалению файла). Так как оповещение является диалогом, он также требует ответа пользователя, прежде чем его можно закрыть. (См. раздел Работа с оповещениями)

Дополнительные сведения см. в разделе "О Windows" в темах дизайна macOS Apple.

Основные, ключи и неактивные окна

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

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

Дополнительные сведения см. в разделе "О Windows" в темах дизайна macOS Apple.

Окна именования

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

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

  • Используйте имя приложения для заголовка основного окна, отличного от документа.
  • Назовите новое окно untitledдокумента. Для первого нового документа не добавляйте число к заголовку (например untitled 1). Если пользователь создает еще один документ перед сохранением и вводом текста в первую очередь, вызовите это окно untitled 2и untitled 3т. д.

Дополнительные сведения см. в разделе именования Windows в темах дизайна macOS Apple.

Полноэкранные окна

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

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

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

Дополнительные сведения см. в разделе "Полноэкранные окна" в темах оформления macOS Apple.

Панели

Панель — это вспомогательное окно, содержащее элементы управления и параметры, влияющие на активный документ или выбор (например, системный средство выбора цветов):

A color panel

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

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

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

Инспекторов

Большинство современных приложений macOS представляют вспомогательные элементы управления и параметры, влияющие на активный документ или выбор в качестве инспекторов , которые входят в основное окно (например , приложение Pages , показанное ниже), вместо использования Панели Windows:

An example inspector

Дополнительные сведения см. в разделе "Панели" в темах дизайна macOS Apple и нашем примере приложения MacInspector для полной реализации интерфейса инспектора в приложении Xamarin.Mac.

Создание и обслуживание окон в Xcode

При создании нового приложения Xamarin.Mac Cocoa вы получаете стандартное пустое окно по умолчанию. Эти окна определяются в файле, который автоматически включается в .storyboard проект. Чтобы изменить дизайн окон, в Обозреватель решений дважды щелкните Main.storyboard файл:

Selecting the main storyboard

Откроется конструктор окон в построителе интерфейсов Xcode:

Editing the UI in Xcode

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

  • Заголовок — это текст, который будет отображаться в заголовке окна.
  • Автосохранение — это ключ , который будет использоваться для идентификации окна при автоматическом сохранении позиции и параметров.
  • Строка заголовка — отображает ли окно строку заголовка.
  • Унифицированный заголовок и панель инструментов. Если окно включает панель инструментов , она должна быть частью строки заголовка.
  • Представление содержимого полного размера — позволяет области содержимого окна находиться в строке заголовка.
  • Тень — имеет ли окно тень.
  • Текстурированные - Текстурированные окна могут использовать эффекты (например, vibrancy) и могут перемещаться вокруг, перетаскивая в любое место их тела.
  • Закрыть — имеет ли окно кнопку закрытия .
  • Свернуть окно с кнопкой свернуть.
  • Изменение размера— имеет ли окно элемент управления изменением размера.
  • Кнопка "Панель инструментов" — есть ли в окне кнопка скрытия или отображения панели инструментов.
  • Можно восстановить. Позиция окна и параметры автоматически сохраняются и восстанавливаются.
  • Видимый при запуске — окно автоматически отображается при .xib загрузке файла.
  • Скрыть деактивацию — окно скрыто, когда приложение входит в фон.
  • Выпуск при закрытии — окно очищается из памяти при закрытии.
  • Подсказки всегда отображаются. Подсказки постоянно отображаются.
  • Перерасчитывает цикл представления . Выполняется пересчет порядка представления перед рисованием окна.
  • Spaces, Exposé и Велоспорт — все определяет, как работает окно в этих средах macOS.
  • Полноэкранный режим— определяет, может ли это окно входить в полноэкранный режим.
  • Анимация — управляет типом анимации, доступной для окна.
  • Внешний вид — управляет внешним видом окна. На данный момент есть только один вид, Aqua.

Дополнительные сведения см. в документации Apple по Windows и NSWindow .

Задание размера и расположения по умолчанию

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

The default size and location

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

Настройка пользовательского контроллера главного окна

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

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

  1. Откройте раскадровку приложения в конструкторе интерфейсов Xcode.

  2. NSWindowController Выберите область конструктора.

  3. Перейдите в представление инспектора удостоверений и введите WindowController имя класса:

    Setting the class name

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

  5. Файл WindowController.cs будет добавлен в проект в Обозреватель решений в Visual Studio для Mac:

    Selecting the windows controller

  6. Откройте раскадровку в построителе интерфейсов Xcode.

  7. Файл WindowController.h будет доступен для использования:

    Editing the WindowController.h file

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

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

Например, давайте перетащите панель инструментов из инспектора библиотеки в окно в редакторе интерфейса:

Selecting a Toolbar from the Library

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

Adding a Text View

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

Editing constraints

Щелкнув четыре красных I-Beams в верхней части редактора и нажав кнопку "Добавить 4 ограничения", мы говорим текстовому представлению, чтобы придерживаться заданных координат X,Y и увеличивать или уменьшать по горизонтали и по вертикали по мере изменения размера окна.

Наконец, предоставьте текстовое представление коду с помощью выхода (обязательно выберите ViewController.h файл):

Configuring an outlet

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

Дополнительные сведения о работе с точкамии действиями см. в нашей документации по выходу и действиям.

Стандартный рабочий процесс окна

Для любого окна, с которым вы создаете и работаете в приложении Xamarin.Mac, процесс в основном совпадает с тем, что мы только что сделали выше:

  1. Для новых окон, которые не добавляются автоматически в проект, добавьте новое определение окна в проект. Это будет подробно описано ниже.
  2. Дважды щелкните Main.storyboard файл, чтобы открыть макет окна для редактирования в конструкторе интерфейсов Xcode.
  3. Перетащите новое окно в дизайн пользовательского интерфейса и подключите окно в главное окно с помощью segues (дополнительные сведения см. в разделе "Segues" документации по работе с раскадровки).
  4. Задайте все необходимые свойства окна в инспекторе атрибутов и инспекторе размера.
  5. Перетащите элементы управления, необходимые для сборки интерфейса, и настройте их в инспекторе атрибутов.
  6. Используйте инспектор размера для обработки изменения размера элементов пользовательского интерфейса.
  7. Предоставление элементов пользовательского интерфейса окна коду C# через точки и действия.
  8. Сохраните изменения и вернитесь в Visual Studio для Mac для синхронизации с Xcode.

Теперь, когда мы создали базовое окно, мы рассмотрим типичные процессы, выполняемые приложением Xamarin.Mac при работе с окнами.

Отображение окна по умолчанию

По умолчанию новое приложение Xamarin.Mac автоматически отобразит окно, определенное MainWindow.xib в файле при запуске:

An example window running

Так как мы изменили макет этого окна выше, теперь он включает панель инструментов по умолчанию и элемент управления "Представление текста". Следующий раздел в Info.plist файле отвечает за отображение этого окна:

Editing Info.plist

Раскрывающийся список "Основной интерфейс" используется для выбора раскадровки, которая будет использоваться в качестве основного пользовательского интерфейса приложения (в данном случае Main.storyboard).

Контроллер представления автоматически добавляется в проект для управления отображением основного окна (наряду с основным представлением). Он определен в ViewController.cs файле и присоединен к владельцу файла в построителе интерфейсов в инспекторе удостоверений:

Setting the file's owner

Для нашего окна мы хотели бы иметь заголовок untitled при первом открытии, чтобы переопределить ViewWillAppear метод в ViewController.cs следующем виде:

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

    // Set Window Title
    this.View.Window.Title = "untitled";
}

Примечание.

Свойство окна Title задано в ViewWillAppear методе вместо ViewDidLoad метода, так как, хотя представление может быть загружено в память, оно еще не полностью создано. Title Доступ к свойству в ViewDidLoad методе мы получим null исключение, так как окно еще не было создано и подключено к свойству.

Программное закрытие окна

Может возникнуть время, когда вы хотите программно закрыть окно в приложении Xamarin.Mac, кроме нажатия пользователем кнопки "Закрыть" или с помощью элемента меню. macOS предоставляет два разных способа закрытия программноPerformClose: NSWindow и Close.

ВыполнениеClose

PerformClose Вызов метода NSWindow имитирует пользователя, щелкнув кнопку "Закрыть" окна, моментальным выделением кнопки и закрытием окна.

Если приложение реализует NSWindowWillClose событие, оно будет поднято до закрытия окна. Если событие возвращается false, окно не будет закрыто. Если окно не имеет кнопки закрытия или не может быть закрыто по какой-либо причине, ОС будет выдавать звук оповещения.

Например:

MyWindow.PerformClose(this);

Попытается закрыть MyWindowNSWindow экземпляр. Если это было успешно, окно будет закрыто, в противном случае будет создан звук оповещения и останется открытым.

Закрытие

Close Вызов метода NSWindow не имитирует пользователя, щелкнув кнопку закрытия окна, на мгновение выделите кнопку, просто закрывает окно.

Окно не должно быть видимым, и NSWindowWillCloseNotification уведомление будет размещено в Центре уведомлений по умолчанию для закрытия окна.

Метод Close отличается двумя важными способами от PerformClose метода:

  1. Он не пытается вызвать WillClose событие.
  2. Он не имитирует пользователя, нажав кнопку "Закрыть", на мгновение выделите кнопку.

Например:

MyWindow.Close();

Будет закрывать MyWindowNSWindow экземпляр.

Измененное содержимое окон

В macOS Apple предоставила возможность сообщить пользователю о том, что содержимое окна (NSWindow) было изменено пользователем и должно быть сохранено. Если окно содержит измененное содержимое, в мини-приложении Close отобразится небольшая черная точка:

A window with the modified marker

Если пользователь пытается закрыть окно или выйти из приложения Mac во время несохраненных изменений содержимого окна, необходимо представить диалоговое окно или модальный лист и разрешить пользователю сначала сохранить изменения:

A save sheet being shown when the window is closed

Маркировка окна как измененного

Чтобы пометить окно как измененное содержимое, используйте следующий код:

// Mark Window content as modified
Window.DocumentEdited = true;

После сохранения изменения снимите измененный флаг с помощью:

// Mark Window content as not modified
Window.DocumentEdited = false;

Сохранение изменений перед закрытием окна

Чтобы отслеживать закрытие окна и разрешение на сохранение измененного содержимого NSWindowDelegate заранее, необходимо создать подкласс и переопределить его WindowShouldClose метод. Например:

using System;
using AppKit;
using System.IO;
using Foundation;

namespace SourceWriter
{
    public class EditorWindowDelegate : NSWindowDelegate
    {
        #region Computed Properties
        public NSWindow Window { get; set;}
        #endregion

        #region constructors
        public EditorWindowDelegate (NSWindow window)
        {
            // Initialize
            this.Window = window;

        }
        #endregion

        #region Override Methods
        public override bool WindowShouldClose (Foundation.NSObject sender)
        {
            // is the window dirty?
            if (Window.DocumentEdited) {
                var alert = new NSAlert () {
                    AlertStyle = NSAlertStyle.Critical,
                    InformativeText = "Save changes to document before closing window?",
                    MessageText = "Save Document",
                };
                alert.AddButton ("Save");
                alert.AddButton ("Lose Changes");
                alert.AddButton ("Cancel");
                var result = alert.RunSheetModal (Window);

                // Take action based on result
                switch (result) {
                case 1000:
                    // Grab controller
                    var viewController = Window.ContentViewController as ViewController;

                    // Already saved?
                    if (Window.RepresentedUrl != null) {
                        var path = Window.RepresentedUrl.Path;

                        // Save changes to file
                        File.WriteAllText (path, viewController.Text);
                        return true;
                    } else {
                        var dlg = new NSSavePanel ();
                        dlg.Title = "Save Document";
                        dlg.BeginSheet (Window, (rslt) => {
                            // File selected?
                            if (rslt == 1) {
                                var path = dlg.Url.Path;
                                File.WriteAllText (path, viewController.Text);
                                Window.DocumentEdited = false;
                                viewController.View.Window.SetTitleWithRepresentedFilename (Path.GetFileName(path));
                                viewController.View.Window.RepresentedUrl = dlg.Url;
                                Window.Close();
                            }
                        });
                        return true;
                    }
                    return false;
                case 1001:
                    // Lose Changes
                    return true;
                case 1002:
                    // Cancel
                    return false;
                }
            }

            return true;
        }
        #endregion
    }
}

Используйте следующий код для присоединения экземпляра этого делегата к окну:

// Set delegate
Window.Delegate = new EditorWindowDelegate(Window);

Сохранение изменений перед закрытием приложения

Наконец, приложение Xamarin.Mac должно проверка, чтобы узнать, содержит ли какой-либо из его Windows измененное содержимое и позволить пользователю сохранять изменения перед выходом. Для этого измените AppDelegate.cs файл, переопределите ApplicationShouldTerminate метод и сделайте его следующим образом:

public override NSApplicationTerminateReply ApplicationShouldTerminate (NSApplication sender)
{
    // See if any window needs to be saved first
    foreach (NSWindow window in NSApplication.SharedApplication.Windows) {
        if (window.Delegate != null && !window.Delegate.WindowShouldClose (this)) {
            // Did the window terminate the close?
            return NSApplicationTerminateReply.Cancel;
        }
    }

    // Allow normal termination
    return NSApplicationTerminateReply.Now;
}

Работа с несколькими окнами

Большинство приложений Mac на основе документов могут одновременно изменять несколько документов. Например, текстовый редактор может одновременно открывать несколько текстовых файлов. По умолчанию в новом приложении Xamarin.Mac есть меню "Файл " с автоматически проводным элементом " newDocument:Действие".

Приведенный ниже код активирует этот новый элемент и позволяет пользователю открывать несколько копий главного окна для одновременного редактирования нескольких документов.

Измените файл и добавьте следующее AppDelegate.cs вычисляемое свойство:

public int UntitledWindowCount { get; set;} =1;

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

Затем добавьте следующий метод:

[Export ("newDocument:")]
void NewDocument (NSObject sender) {
    // Get new window
    var storyboard = NSStoryboard.FromName ("Main", null);
    var controller = storyboard.InstantiateControllerWithIdentifier ("MainWindow") as NSWindowController;

    // Display
    controller.ShowWindow(this);

    // Set the title
    controller.Window.Title = (++UntitledWindowCount == 1) ? "untitled" : string.Format ("untitled {0}", UntitledWindowCount);
}

Этот код создает новую версию контроллера окна, загружает новое окно, делает его основным и ключевым окном и задает его заголовок. Теперь, если мы запустите приложение, и выберите "Создать" в меню "Файл ", откроется и отобразится новое окно редактора:

A new untitled window was added

Если открыть меню Windows , вы увидите, что приложение автоматически отслеживает и обрабатывает наши открытые окна:

The windows menu

Дополнительные сведения о работе с меню в приложении Xamarin.Mac см. в документации по работе с меню .

Получение активного окна

В приложении Xamarin.Mac, которое может открывать несколько окон (документов), возникает время, когда вам потребуется получить текущее, самое верхнее окно (окно ключа). Следующий код возвращает окно ключа:

var window = NSApplication.SharedApplication.KeyWindow;

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

Доступ ко всем окнам приложений

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

Windows Сохраняет NSApplication.SharedApplication свойство, содержащее массив всех открытых окон в приложении. Вы можете выполнить итерацию по этому массиву, чтобы получить доступ ко всем текущим окнам приложения. Например:

// Is the file already open?
for(int n=0; n<NSApplication.SharedApplication.Windows.Length; ++n) {
    var content = NSApplication.SharedApplication.Windows[n].ContentViewController as ViewController;
    if (content != null && path == content.FilePath) {
        // Bring window to front
        NSApplication.SharedApplication.Windows[n].MakeKeyAndOrderFront(this);
        return true;
    }
}

В примере кода мы приведение каждого возвращаемого окна к пользовательскому классу в нашем приложении и тестирование значения настраиваемого ViewControllerPath свойства по пути к файлу, который пользователь хочет открыть. Если файл уже открыт, мы переносим это окно на передний план.

Настройка размера окна в коде

Существует время, когда приложению необходимо изменить размер окна в коде. Чтобы изменить размер окна и изменить его положение, вы измените его Frame свойство. При настройке размера окна обычно необходимо также настроить его источник, чтобы сохранить окно в том же расположении из-за системы координат macOS.

В отличие от iOS, где верхний левый угол представляет (0,0), macOS использует математическую систему координат, где нижний левый угол экрана представляет (0,0). В iOS координаты увеличиваются при переходе вниз к правому краю. В macOS координаты увеличиваются вверх к правому краю.

В следующем примере кода изменяется размер окна:

nfloat y = 0;

// Calculate new origin
y = Frame.Y - (768 - Frame.Height);

// Resize and position window
CGRect frame = new CGRect (Frame.X, y, 1024, 768);
SetFrame (frame, true);

Внимание

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

Изменение размера окна мониторинга

Иногда требуется отслеживать изменения размера окна в приложении Xamarin.Mac. Например, чтобы изменить содержимое в соответствии с новым размером.

Чтобы отслеживать изменения размера, сначала убедитесь, что вы назначили пользовательский класс для контроллера окна в построителе интерфейсов Xcode. Например, MasterWindowController в следующем:

The Identity Inspector

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

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

    Window.DidResize += (sender, e) => {
        // Do something as the window is being live resized
    };
}

При необходимости можно использовать DidEndLiveResize событие только после завершения изменения размера окна. Пример:

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

        Window.DidEndLiveResize += (sender, e) => {
        // Do something after the user's finished resizing
        // the window
    };
}

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

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

Давайте отредактируем наш ViewController.cs файл и внесите следующие изменения:

public bool DocumentEdited {
    get { return View.Window.DocumentEdited; }
    set { View.Window.DocumentEdited = value; }
}
...

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

    // Set Window Title
    this.View.Window.Title = "untitled";

    View.Window.WillClose += (sender, e) => {
        // is the window dirty?
        if (DocumentEdited) {
            var alert = new NSAlert () {
                AlertStyle = NSAlertStyle.Critical,
                InformativeText = "We need to give the user the ability to save the document here...",
                MessageText = "Save Document",
            };
            alert.RunModal ();
        }
    };
}

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

    // Show when the document is edited
    DocumentEditor.TextDidChange += (sender, e) => {
        // Mark the document as dirty
        DocumentEdited = true;
    };

    // Overriding this delegate is required to monitor the TextDidChange event
    DocumentEditor.ShouldChangeTextInRanges += (NSTextView view, NSValue[] values, string[] replacements) => {
        return true;
    };

}

Мы также отслеживаем WillClose событие в окне и проверка состояние DocumentEdited свойства. true Если нужно предоставить пользователю возможность сохранить изменения в файле. Если мы запускаем приложение и введем текст, будет отображаться точка:

A changed window

Если вы попытаетесь закрыть окно, вы получите оповещение:

Displaying a save dialog

Если документ загружается из файла, задайте заголовок окна именем файла с помощью window.SetTitleWithRepresentedFilename (Path.GetFileName(path)); метода (учитывая, что path это строка, представляющая открываемый файл). Кроме того, можно задать URL-адрес файла с помощью window.RepresentedUrl = url; метода.

Если URL-адрес указывает на тип файла, известный ОС, его значок будет отображаться в строке заголовка. Если пользователь щелкает значок правой кнопкой мыши, будет показан путь к файлу.

Измените AppDelegate.cs файл и добавьте следующий метод:

[Export ("openDocument:")]
void OpenDialog (NSObject sender)
{
    var dlg = NSOpenPanel.OpenPanel;
    dlg.CanChooseFiles = true;
    dlg.CanChooseDirectories = false;

    if (dlg.RunModal () == 1) {
        // Nab the first file
        var url = dlg.Urls [0];

        if (url != null) {
            var path = url.Path;

            // Get new window
            var storyboard = NSStoryboard.FromName ("Main", null);
            var controller = storyboard.InstantiateControllerWithIdentifier ("MainWindow") as NSWindowController;

            // Display
            controller.ShowWindow(this);

            // Load the text into the window
            var viewController = controller.Window.ContentViewController as ViewController;
            viewController.Text = File.ReadAllText(path);
                    viewController.View.Window.SetTitleWithRepresentedFilename (Path.GetFileName(path));
            viewController.View.Window.RepresentedUrl = url;

        }
    }
}

Теперь, если мы запустите наше приложение, в меню "Файл" выберите текстовый файл в диалоговом окне "Открыть" и откройте его:

An open dialog box

Файл будет отображаться, и заголовок будет задан с значком файла:

The contents of a file loaded

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

Помимо основного окна документа, приложению Xamarin.Mac может потребоваться отобразить другие типы окон для пользователя, например настройки или панели инспекторов.

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

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

  2. Перетащите новый контроллер окна из библиотекии удалите его на поверхность конструктора:

    Selecting a new Window Controller in the Library

  3. В инспекторе удостоверений введите PreferencesWindowидентификатор раскадровки:

    Setting the storyboard ID

  4. Проектирование интерфейса:

    Designing the UI

  5. Откройте меню приложения (MacWindows), выберите параметры..., щелкните элемент управления и перетащите его в новое окно:

    Creating a segue

  6. Выберите "Показать " в всплывающем меню.

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

Если вы запустите код и выберите параметрыиз меню приложения, откроется окно:

A sample preferences menu

Работа с панелями

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

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

  1. Добавьте новое определение окна в проект.
  2. Дважды щелкните .xib файл, чтобы открыть макет окна для редактирования в конструкторе интерфейсов Xcode.
  3. Задайте все необходимые свойства окна в инспекторе атрибутов и инспекторе размера.
  4. Перетащите элементы управления, необходимые для сборки интерфейса, и настройте их в инспекторе атрибутов.
  5. Используйте инспектор размера для обработки изменения размера элементов пользовательского интерфейса.
  6. Предоставление элементов пользовательского интерфейса окна коду C# через точки и действия.
  7. Сохраните изменения и вернитесь в Visual Studio для Mac для синхронизации с Xcode.

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

The Attribute Inspector

  • Стиль . Позволяет настроить стиль панели с: обычная панель (выглядит как стандартное окно), панель служебной программы (имеет меньшую строку заголовка), huD Panel (является полупрозрачной, а строка заголовка является частью фона).
  • Без активации — определяется на панели становится окном ключа.
  • Модальный документ — если модал документа, панель будет плавать только над окнами приложения, в противном случае она плавает над всеми.

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

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

  2. В диалоговом окне "Создать файл" выберите окно Какао Xamarin.Mac>с контроллером:

    Adding a new window controller

  3. Введите в поле Имя значение DocumentPanel и нажмите кнопку Новый.

  4. Дважды щелкните DocumentPanel.xib файл, чтобы открыть его для редактирования в Конструкторе интерфейсов:

    Editing the panel

  5. Удалите существующее окно и перетащите панель из инспектора библиотеки в редакторе интерфейса:

    Deleting the existing window

  6. Подключите панель к окну - владельца - файла:

    Dragging to wire up the panel

  7. Переключитесь на инспектор удостоверений и задайте для класса DocumentPanelПанели значение :

    Setting the panel's class

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

  9. Измените файл и измените DocumentPanel.cs определение класса следующим образом:

    public partial class DocumentPanel : NSPanel

  10. Сохраните изменения в файле.

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

public override void DidFinishLaunching (NSNotification notification)
{
        // Display panel
    var panel = new DocumentPanelController ();
    panel.Window.MakeKeyAndOrderFront (this);
}

Если мы запускаем наше приложение, откроется панель:

The panel in a running app

Внимание

Панель Windows устарела apple и должна быть заменена интерфейсами инспекторов. Полный пример создания инспектора в приложении Xamarin.Mac см. в нашем примере приложения MacInspector.

Итоги

В этой статье подробно рассматривается работа с Windows и Панелями в приложении Xamarin.Mac. Мы видели различные типы и использование Windows и панелей, как создавать и поддерживать Windows и Панели в построителе интерфейсов Xcode и как работать с Windows и Панелями в коде C#.