Диалоги в Xamarin.Mac
При работе с C# и .NET в приложении Xamarin.Mac у вас есть доступ к тем же диалогам и модальным Windows, в которых работает Objective-C разработчик и Xcode . Так как Xamarin.Mac интегрируется непосредственно с Xcode, вы можете использовать построитель интерфейсов Xcode для создания и поддержания модального Windows (или при необходимости создания их непосредственно в коде C#).
Диалоговое окно отображается в ответ на действие пользователя и обычно предоставляет способы выполнения действия пользователями. Для закрытия диалогового окна требуется ответ от пользователя.
Windows можно использовать в режиме без режима (например, текстовый редактор, который может одновременно открывать несколько документов) или модал (например, диалоговое окно экспорта, которое должно быть отклонено до продолжения приложения).
В этой статье мы рассмотрим основы работы с диалогами и модальными окнами в приложении Xamarin.Mac. Настоятельно рекомендуется сначала ознакомиться со статьей Hello, Mac , в частности в разделах "Введение в Xcode" и "Конструктор интерфейсов" и "Торговых точек" и "Действия ", поскольку рассматриваются основные понятия и методы, которые мы будем использовать в этой статье.
Вы можете ознакомиться с классами И методами C# в Objective-Cразделе документа Xamarin.Mac Internals, а также объяснить Register
Export
команды, используемые для подключения классов C# к Objective-C объектам и элементам пользовательского интерфейса.
Общие сведения о диалогах
Диалоговое окно отображается в ответ на действие пользователя (например, сохранение файла) и позволяет пользователям выполнить это действие. Для закрытия диалогового окна требуется ответ от пользователя.
По словам Apple, существует три способа представления диалога:
- Модальное диалоговое окно документа — диалоговое окно "Модальный документ" запрещает пользователю делать что-либо другое в заданном документе до тех пор, пока он не будет закрыт.
- Модальное окно приложения — диалоговое окно модального приложения запрещает пользователю взаимодействовать с приложением до тех пор, пока он не будет закрыт.
- Бессерверное диалоговое окно A позволяет пользователям изменять параметры в диалоговом окне при взаимодействии с окном документа.
Модальное окно
Любой стандарт NSWindow
можно использовать в качестве настраиваемого диалогового окна, отображая его модально:
Модальные листы диалоговых окон документа
Лист — это модальное диалоговое окно, которое присоединено к заданному окну документа, предотвращая взаимодействие пользователей с окном, пока они не уволят диалоговое окно. Лист присоединяется к окну, из которого она возникает, и только один лист может быть открыт для окна в любое время.
Параметры Windows
Окно параметров — это бессерверное диалоговое окно, содержащее параметры приложения, которые пользователь редко изменяет. Параметры Windows часто включают панель инструментов, которая позволяет пользователю переключаться между различными группами параметров:
Открыть диалоговое окно
Диалоговое окно "Открыть" предоставляет пользователям согласованный способ поиска и открытия элемента в приложении:
Диалоговые окна настройки печати и страницы
macOS предоставляет стандартные диалоговые окна настройки печати и страницы, которые могут отображаться в приложении, чтобы пользователи могли иметь согласованные возможности печати в каждом приложении, которое они используют.
Диалоговое окно печати может отображаться как свободное плавающее диалоговое окно:
Или его можно отобразить как лист:
Диалоговое окно установки страницы может отображаться как свободное диалоговое окно с плавающей запятой:
Или его можно отобразить как лист:
Сохранение диалогов
Диалоговое окно "Сохранить" предоставляет пользователям согласованный способ сохранения элемента в приложении. Диалоговое окно сохранения имеет два состояния: минимальное (также известное как свернутый):
И развернутое состояние:
Диалоговое окно "Минимальное сохранение" также можно отобразить в виде листа:
Как можно развернуть диалоговое окно сохранения:
Дополнительные сведения см. в разделе "Диалоги " руководства по пользовательскому интерфейсу Apple OS X
Добавление модального окна в проект
Помимо основного окна документа, приложению Xamarin.Mac может потребоваться отобразить другие типы окон для пользователя, например настройки или панели инспекторов.
Чтобы добавить новое окно, сделайте следующее:
В Обозреватель решений откройте
Main.storyboard
файл для редактирования в построителе интерфейсов Xcode.Перетащите новый контроллер представления в область конструктора:
В инспекторе удостоверений введите
CustomDialogController
имя класса:Вернитесь к Visual Studio для Mac, разрешите ему синхронизироваться с Xcode и создать
CustomDialogController.h
файл.Вернитесь к Xcode и создайте интерфейс:
Создайте модальный segue из главного окна приложения к новому контроллеру представления, перетаскивая элемент управления из элемента пользовательского интерфейса, который откроет диалоговое окно в окно диалогового окна. Назначьте идентификатор
ModalSegue
:Проводка любых действий и выходов:
Сохраните изменения и вернитесь к Visual Studio для Mac для синхронизации с Xcode.
Сделайте CustomDialogController.cs
файл следующим образом:
using System;
using Foundation;
using AppKit;
namespace MacDialog
{
public partial class CustomDialogController : NSViewController
{
#region Private Variables
private string _dialogTitle = "Title";
private string _dialogDescription = "Description";
private NSViewController _presentor;
#endregion
#region Computed Properties
public string DialogTitle {
get { return _dialogTitle; }
set { _dialogTitle = value; }
}
public string DialogDescription {
get { return _dialogDescription; }
set { _dialogDescription = value; }
}
public NSViewController Presentor {
get { return _presentor; }
set { _presentor = value; }
}
#endregion
#region Constructors
public CustomDialogController (IntPtr handle) : base (handle)
{
}
#endregion
#region Override Methods
public override void ViewWillAppear ()
{
base.ViewWillAppear ();
// Set initial title and description
Title.StringValue = DialogTitle;
Description.StringValue = DialogDescription;
}
#endregion
#region Private Methods
private void CloseDialog() {
Presentor.DismissViewController (this);
}
#endregion
#region Custom Actions
partial void AcceptDialog (Foundation.NSObject sender) {
RaiseDialogAccepted();
CloseDialog();
}
partial void CancelDialog (Foundation.NSObject sender) {
RaiseDialogCanceled();
CloseDialog();
}
#endregion
#region Events
public EventHandler DialogAccepted;
internal void RaiseDialogAccepted() {
if (this.DialogAccepted != null)
this.DialogAccepted (this, EventArgs.Empty);
}
public EventHandler DialogCanceled;
internal void RaiseDialogCanceled() {
if (this.DialogCanceled != null)
this.DialogCanceled (this, EventArgs.Empty);
}
#endregion
}
}
Этот код предоставляет несколько свойств, чтобы задать заголовок и описание диалогового окна, а также несколько событий для реагирования на отмену или принятие диалогового окна.
Затем измените ViewController.cs
файл, переопределите PrepareForSegue
метод и сделайте его следующим образом:
public override void PrepareForSegue (NSStoryboardSegue segue, NSObject sender)
{
base.PrepareForSegue (segue, sender);
// Take action based on the segue name
switch (segue.Identifier) {
case "ModalSegue":
var dialog = segue.DestinationController as CustomDialogController;
dialog.DialogTitle = "MacDialog";
dialog.DialogDescription = "This is a sample dialog.";
dialog.DialogAccepted += (s, e) => {
Console.WriteLine ("Dialog accepted");
DismissViewController (dialog);
};
dialog.Presentor = this;
break;
}
}
Этот код инициализирует segue, определенный в построителе интерфейсов Xcode в нашем диалоговом окне, и настраивает заголовок и описание. Он также обрабатывает выбор пользователя в диалоговом окне.
Мы можем запустить приложение и отобразить настраиваемое диалоговое окно:
Дополнительные сведения об использовании окон в приложении Xamarin.Mac см. в нашей документации по Работе с Windows .
Создание настраиваемого листа
Лист — это модальное диалоговое окно, которое присоединено к заданному окну документа, предотвращая взаимодействие пользователей с окном, пока они не уволят диалоговое окно. Лист присоединяется к окну, из которого она возникает, и только один лист может быть открыт для окна в любое время.
Чтобы создать пользовательский лист в Xamarin.Mac, давайте сделаем следующее:
В Обозреватель решений откройте
Main.storyboard
файл для редактирования в построителе интерфейсов Xcode.Перетащите новый контроллер представления в область конструктора:
Проектирование пользовательского интерфейса:
Создайте сег листа из главного окна на новый контроллер представления:
В инспекторе удостоверений назовите класс
SheetViewController
контроллера представления:Определите все необходимые точки и действия:
Сохраните изменения и вернитесь к Visual Studio для Mac для синхронизации.
Затем измените SheetViewController.cs
файл и сделайте его следующим образом:
using System;
using Foundation;
using AppKit;
namespace MacDialog
{
public partial class SheetViewController : NSViewController
{
#region Private Variables
private string _userName = "";
private string _password = "";
private NSViewController _presentor;
#endregion
#region Computed Properties
public string UserName {
get { return _userName; }
set { _userName = value; }
}
public string Password {
get { return _password;}
set { _password = value;}
}
public NSViewController Presentor {
get { return _presentor; }
set { _presentor = value; }
}
#endregion
#region Constructors
public SheetViewController (IntPtr handle) : base (handle)
{
}
#endregion
#region Override Methods
public override void ViewWillAppear ()
{
base.ViewWillAppear ();
// Set initial values
NameField.StringValue = UserName;
PasswordField.StringValue = Password;
// Wireup events
NameField.Changed += (sender, e) => {
UserName = NameField.StringValue;
};
PasswordField.Changed += (sender, e) => {
Password = PasswordField.StringValue;
};
}
#endregion
#region Private Methods
private void CloseSheet() {
Presentor.DismissViewController (this);
}
#endregion
#region Custom Actions
partial void AcceptSheet (Foundation.NSObject sender) {
RaiseSheetAccepted();
CloseSheet();
}
partial void CancelSheet (Foundation.NSObject sender) {
RaiseSheetCanceled();
CloseSheet();
}
#endregion
#region Events
public EventHandler SheetAccepted;
internal void RaiseSheetAccepted() {
if (this.SheetAccepted != null)
this.SheetAccepted (this, EventArgs.Empty);
}
public EventHandler SheetCanceled;
internal void RaiseSheetCanceled() {
if (this.SheetCanceled != null)
this.SheetCanceled (this, EventArgs.Empty);
}
#endregion
}
}
Затем измените ViewController.cs
файл, измените PrepareForSegue
метод и сделайте его следующим образом:
public override void PrepareForSegue (NSStoryboardSegue segue, NSObject sender)
{
base.PrepareForSegue (segue, sender);
// Take action based on the segue name
switch (segue.Identifier) {
case "ModalSegue":
var dialog = segue.DestinationController as CustomDialogController;
dialog.DialogTitle = "MacDialog";
dialog.DialogDescription = "This is a sample dialog.";
dialog.DialogAccepted += (s, e) => {
Console.WriteLine ("Dialog accepted");
DismissViewController (dialog);
};
dialog.Presentor = this;
break;
case "SheetSegue":
var sheet = segue.DestinationController as SheetViewController;
sheet.SheetAccepted += (s, e) => {
Console.WriteLine ("User Name: {0} Password: {1}", sheet.UserName, sheet.Password);
};
sheet.Presentor = this;
break;
}
}
Если мы запускаем приложение и открываем лист, он будет присоединен к окну:
Создание диалогового окна параметров
Прежде чем выложить представление предпочтений в построителе интерфейсов, необходимо добавить настраиваемый тип segue для обработки переключения параметров. Добавьте новый класс в проект и вызовите его ReplaceViewSeque
. Измените класс и сделайте его следующим образом:
using System;
using AppKit;
using Foundation;
namespace MacWindows
{
[Register("ReplaceViewSeque")]
public class ReplaceViewSeque : NSStoryboardSegue
{
#region Constructors
public ReplaceViewSeque() {
}
public ReplaceViewSeque (string identifier, NSObject sourceController, NSObject destinationController) : base(identifier,sourceController,destinationController) {
}
public ReplaceViewSeque (IntPtr handle) : base(handle) {
}
public ReplaceViewSeque (NSObjectFlag x) : base(x) {
}
#endregion
#region Override Methods
public override void Perform ()
{
// Cast the source and destination controllers
var source = SourceController as NSViewController;
var destination = DestinationController as NSViewController;
// Is there a source?
if (source == null) {
// No, get the current key window
var window = NSApplication.SharedApplication.KeyWindow;
// Swap the controllers
window.ContentViewController = destination;
// Release memory
window.ContentViewController?.RemoveFromParentViewController ();
} else {
// Swap the controllers
source.View.Window.ContentViewController = destination;
// Release memory
source.RemoveFromParentViewController ();
}
}
#endregion
}
}
С помощью созданного пользовательского segue можно добавить новое окно в построителе интерфейсов Xcode для обработки наших предпочтений.
Чтобы добавить новое окно, сделайте следующее:
В Обозреватель решений откройте
Main.storyboard
файл для редактирования в построителе интерфейсов Xcode.Перетащите новый контроллер окна в область конструктора:
Упорядочение окна рядом с конструктором строк меню:
Создайте копии подключенного контроллера представления, так как в представлении предпочтений будут вкладки:
Перетащите новый контроллер панели инструментов из библиотеки:
И удалите его в окне в области конструктора:
Макет макета панели инструментов:
Щелкните элемент управления и перетащите с каждой кнопки панели инструментов в созданные выше представления. Выберите тип пользовательского segue:
Выберите новый segue и задайте для класса
ReplaceViewSegue
значение :В конструкторе панели меню в области конструктора в меню "Приложение" выберите "Параметры"..., щелкните элемент управления и перетащите его в окно "Настройки", чтобы создать сеге "Показать":
Сохраните изменения и вернитесь к Visual Studio для Mac для синхронизации.
Если вы запустите код и выберите параметры из меню приложения, откроется окно:
Дополнительные сведения о работе с Windows и панели инструментов см. в нашей документации по Windows и панели инструментов.
Сохранение и загрузка параметров
В обычном приложении macOS, когда пользователь вносит изменения в любой из параметров пользователя приложения, эти изменения сохраняются автоматически. Самый простой способ справиться с этим в приложении Xamarin.Mac — создать один класс для управления всеми предпочтениями пользователя и совместно использовать его на уровне системы.
Сначала добавьте новый AppPreferences
класс в проект и наследуйте от NSObject
него. Параметры будут предназначены для использования привязки данных и кодирования ключа, что сделает процесс создания и поддержания форм предпочтений гораздо проще. Так как параметры будут состоять из небольшого количества простых типов данных, используйте встроенный для NSUserDefaults
хранения и извлечения значений.
Измените AppPreferences.cs
файл и сделайте его следующим образом:
using System;
using Foundation;
using AppKit;
namespace SourceWriter
{
[Register("AppPreferences")]
public class AppPreferences : NSObject
{
#region Computed Properties
[Export("DefaultLanguage")]
public int DefaultLanguage {
get {
var value = LoadInt ("DefaultLanguage", 0);
return value;
}
set {
WillChangeValue ("DefaultLanguage");
SaveInt ("DefaultLanguage", value, true);
DidChangeValue ("DefaultLanguage");
}
}
[Export("SmartLinks")]
public bool SmartLinks {
get { return LoadBool ("SmartLinks", true); }
set {
WillChangeValue ("SmartLinks");
SaveBool ("SmartLinks", value, true);
DidChangeValue ("SmartLinks");
}
}
// Define any other required user preferences in the same fashion
...
[Export("EditorBackgroundColor")]
public NSColor EditorBackgroundColor {
get { return LoadColor("EditorBackgroundColor", NSColor.White); }
set {
WillChangeValue ("EditorBackgroundColor");
SaveColor ("EditorBackgroundColor", value, true);
DidChangeValue ("EditorBackgroundColor");
}
}
#endregion
#region Constructors
public AppPreferences ()
{
}
#endregion
#region Public Methods
public int LoadInt(string key, int defaultValue) {
// Attempt to read int
var number = NSUserDefaults.StandardUserDefaults.IntForKey(key);
// Take action based on value
if (number == null) {
return defaultValue;
} else {
return (int)number;
}
}
public void SaveInt(string key, int value, bool sync) {
NSUserDefaults.StandardUserDefaults.SetInt(value, key);
if (sync) NSUserDefaults.StandardUserDefaults.Synchronize ();
}
public bool LoadBool(string key, bool defaultValue) {
// Attempt to read int
var value = NSUserDefaults.StandardUserDefaults.BoolForKey(key);
// Take action based on value
if (value == null) {
return defaultValue;
} else {
return value;
}
}
public void SaveBool(string key, bool value, bool sync) {
NSUserDefaults.StandardUserDefaults.SetBool(value, key);
if (sync) NSUserDefaults.StandardUserDefaults.Synchronize ();
}
public string NSColorToHexString(NSColor color, bool withAlpha) {
//Break color into pieces
nfloat red=0, green=0, blue=0, alpha=0;
color.GetRgba (out red, out green, out blue, out alpha);
// Adjust to byte
alpha *= 255;
red *= 255;
green *= 255;
blue *= 255;
//With the alpha value?
if (withAlpha) {
return String.Format ("#{0:X2}{1:X2}{2:X2}{3:X2}", (int)alpha, (int)red, (int)green, (int)blue);
} else {
return String.Format ("#{0:X2}{1:X2}{2:X2}", (int)red, (int)green, (int)blue);
}
}
public NSColor NSColorFromHexString (string hexValue)
{
var colorString = hexValue.Replace ("#", "");
float red, green, blue, alpha;
// Convert color based on length
switch (colorString.Length) {
case 3 : // #RGB
red = Convert.ToInt32(string.Format("{0}{0}", colorString.Substring(0, 1)), 16) / 255f;
green = Convert.ToInt32(string.Format("{0}{0}", colorString.Substring(1, 1)), 16) / 255f;
blue = Convert.ToInt32(string.Format("{0}{0}", colorString.Substring(2, 1)), 16) / 255f;
return NSColor.FromRgba(red, green, blue, 1.0f);
case 6 : // #RRGGBB
red = Convert.ToInt32(colorString.Substring(0, 2), 16) / 255f;
green = Convert.ToInt32(colorString.Substring(2, 2), 16) / 255f;
blue = Convert.ToInt32(colorString.Substring(4, 2), 16) / 255f;
return NSColor.FromRgba(red, green, blue, 1.0f);
case 8 : // #AARRGGBB
alpha = Convert.ToInt32(colorString.Substring(0, 2), 16) / 255f;
red = Convert.ToInt32(colorString.Substring(2, 2), 16) / 255f;
green = Convert.ToInt32(colorString.Substring(4, 2), 16) / 255f;
blue = Convert.ToInt32(colorString.Substring(6, 2), 16) / 255f;
return NSColor.FromRgba(red, green, blue, alpha);
default :
throw new ArgumentOutOfRangeException(string.Format("Invalid color value '{0}'. It should be a hex value of the form #RBG, #RRGGBB or #AARRGGBB", hexValue));
}
}
public NSColor LoadColor(string key, NSColor defaultValue) {
// Attempt to read color
var hex = NSUserDefaults.StandardUserDefaults.StringForKey(key);
// Take action based on value
if (hex == null) {
return defaultValue;
} else {
return NSColorFromHexString (hex);
}
}
public void SaveColor(string key, NSColor color, bool sync) {
// Save to default
NSUserDefaults.StandardUserDefaults.SetString(NSColorToHexString(color,true), key);
if (sync) NSUserDefaults.StandardUserDefaults.Synchronize ();
}
#endregion
}
}
Этот класс содержит несколько вспомогательных подпрограмм, таких как SaveInt
, LoadInt
, SaveColor
и LoadColor
т. д. для упрощения работы NSUserDefaults
. Кроме того, так как NSUserDefaults
не имеет встроенного способа обработки NSColors
, NSColorToHexString
методы NSColorFromHexString
используются для преобразования цветов в шестнадцатеричные строки на основе веб-сайтов (#RRGGBBAA
где AA
альфа-прозрачность), которые можно легко хранить и извлекать.
AppDelegate.cs
В файле создайте экземпляр объекта AppPreferences, который будет использоваться на уровне приложения:
using AppKit;
using Foundation;
using System.IO;
using System;
namespace SourceWriter
{
[Register ("AppDelegate")]
public class AppDelegate : NSApplicationDelegate
{
#region Computed Properties
public int NewWindowNumber { get; set;} = -1;
public AppPreferences Preferences { get; set; } = new AppPreferences();
#endregion
#region Constructors
public AppDelegate ()
{
}
#endregion
...
Параметры подключения к представлениям предпочтений
Затем подключите класс предпочтения к элементам пользовательского интерфейса в окне предпочтения и представлениях, созданных выше. В построителе интерфейсов выберите контроллер представления предпочтений и перейдите в инспектор удостоверений, создайте пользовательский класс для контроллера:
Вернитесь к Visual Studio для Mac для синхронизации изменений и откройте только что созданный класс для редактирования. Сделайте класс следующим образом:
using System;
using Foundation;
using AppKit;
namespace SourceWriter
{
public partial class EditorPrefsController : NSViewController
{
#region Application Access
public static AppDelegate App {
get { return (AppDelegate)NSApplication.SharedApplication.Delegate; }
}
#endregion
#region Computed Properties
[Export("Preferences")]
public AppPreferences Preferences {
get { return App.Preferences; }
}
#endregion
#region Constructors
public EditorPrefsController (IntPtr handle) : base (handle)
{
}
#endregion
}
}
Обратите внимание, что этот класс сделал два действия здесь: во-первых, есть вспомогательное App
свойство, чтобы упростить доступ к AppDelegate . Во-вторых, Preferences
свойство предоставляет глобальный класс AppPreferences для привязки данных с любыми элементами управления пользовательского интерфейса, размещенными в этом представлении.
Затем дважды щелкните файл раскадровки, чтобы повторно открыть его в построителе интерфейсов (и просмотреть изменения, внесенные выше). Перетащите все элементы управления пользовательского интерфейса, необходимые для создания интерфейса параметров в представлении. Для каждого элемента управления перейдите к инспектору привязки и привязать к отдельным свойствам класса AppPreference :
Повторите описанные выше действия для всех панелей (контроллеров представления) и необходимых свойств предпочтения.
Применение изменений предпочтений ко всем открытым окнам
Как упоминалось выше, в обычном приложении macOS, когда пользователь вносит изменения в любой из параметров пользователя приложения, эти изменения сохраняются автоматически и применяются к любым окнам, которые пользователь может открыть в приложении.
Тщательное планирование и проектирование настроек и окон приложения позволит этому процессу плавно и прозрачно работать с конечным пользователем с минимальным объемом работы по программированию.
Для любого окна, которое будет использовать параметры приложения, добавьте следующее вспомогательное свойство в контроллер представления содержимого, чтобы упростить доступ к нашему AppDelegate :
#region Application Access
public static AppDelegate App {
get { return (AppDelegate)NSApplication.SharedApplication.Delegate; }
}
#endregion
Затем добавьте класс для настройки содержимого или поведения на основе предпочтений пользователя:
public void ConfigureEditor() {
// General Preferences
TextEditor.AutomaticLinkDetectionEnabled = App.Preferences.SmartLinks;
TextEditor.AutomaticQuoteSubstitutionEnabled = App.Preferences.SmartQuotes;
...
}
Необходимо вызвать метод конфигурации при первом открытии окна, чтобы убедиться, что он соответствует предпочтениям пользователя:
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
// Configure editor from user preferences
ConfigureEditor ();
...
}
Затем измените AppDelegate.cs
файл и добавьте следующий метод, чтобы применить любые изменения предпочтений ко всем открытым окнам:
public void UpdateWindowPreferences() {
// Process all open windows
for(int n=0; n<NSApplication.SharedApplication.Windows.Length; ++n) {
var content = NSApplication.SharedApplication.Windows[n].ContentViewController as ViewController;
if (content != null ) {
// Reformat all text
content.ConfigureEditor ();
}
}
}
Затем добавьте PreferenceWindowDelegate
класс в проект и сделайте его следующим образом:
using System;
using AppKit;
using System.IO;
using Foundation;
namespace SourceWriter
{
public class PreferenceWindowDelegate : NSWindowDelegate
{
#region Application Access
public static AppDelegate App {
get { return (AppDelegate)NSApplication.SharedApplication.Delegate; }
}
#endregion
#region Computed Properties
public NSWindow Window { get; set;}
#endregion
#region constructors
public PreferenceWindowDelegate (NSWindow window)
{
// Initialize
this.Window = window;
}
#endregion
#region Override Methods
public override bool WindowShouldClose (Foundation.NSObject sender)
{
// Apply any changes to open windows
App.UpdateWindowPreferences();
return true;
}
#endregion
}
}
Это приведет к тому, что все изменения предпочтений будут отправляться во все открытые Окна при закрытии окна предпочтений.
Наконец, измените контроллер окна предпочтения и добавьте делегат, созданный выше:
using System;
using Foundation;
using AppKit;
namespace SourceWriter
{
public partial class PreferenceWindowController : NSWindowController
{
#region Constructors
public PreferenceWindowController (IntPtr handle) : base (handle)
{
}
#endregion
#region Override Methods
public override void WindowDidLoad ()
{
base.WindowDidLoad ();
// Initialize
Window.Delegate = new PreferenceWindowDelegate(Window);
Toolbar.SelectedItemIdentifier = "General";
}
#endregion
}
}
При всех этих изменениях, если пользователь изменяет настройки приложения и закрывает окно предпочтения, изменения будут применены ко всем открытым Окнам Windows:
Диалоговое окно "Открыть"
Диалоговое окно "Открыть" предоставляет пользователям согласованный способ поиска и открытия элемента в приложении. Чтобы открыть диалоговое окно в приложении Xamarin.Mac, используйте следующий код:
var dlg = NSOpenPanel.OpenPanel;
dlg.CanChooseFiles = true;
dlg.CanChooseDirectories = false;
dlg.AllowedFileTypes = new string[] { "txt", "html", "md", "css" };
if (dlg.RunModal () == 1) {
// Nab the first file
var url = dlg.Urls [0];
if (url != null) {
var path = url.Path;
// Create a new window to hold the text
var newWindowController = new MainWindowController ();
newWindowController.Window.MakeKeyAndOrderFront (this);
// Load the text into the window
var window = newWindowController.Window as MainWindow;
window.Text = File.ReadAllText(path);
window.SetTitleWithRepresentedFilename (Path.GetFileName(path));
window.RepresentedUrl = url;
}
}
В приведенном выше коде мы открываем новое окно документа для отображения содержимого файла. Вам потребуется заменить этот код функциональными возможностями приложения.
Следующие свойства доступны при работе с:NSOpenPanel
- CanChooseFiles — если
true
пользователь может выбрать файлы. - CanChooseDirectory — если
true
пользователь может выбрать каталоги. - РазрешитьMultipleSelection — если
true
пользователь может выбрать несколько файлов одновременно. - ResolveAliases — если
true
выбран и псевдоним, разрешает его путь к исходному файлу. - AllowedFileTypes — это строковый массив типов файлов, которые пользователь может выбрать как расширение или UTI. Значением по умолчанию является
null
, что позволяет открывать любой файл.
Метод RunModal ()
отображает диалоговое окно "Открыть" и позволяет пользователю выбирать файлы или каталоги (как указано в свойствах) и возвращается 1
, если пользователь нажимает кнопку "Открыть ".
Диалоговое окно "Открыть" возвращает выбранные файлы или каталоги пользователя в виде массива URL-адресов в свойстве URL
.
Если запустить программу и выбрать элемент Open... в меню "Файл ", отобразится следующее:
Диалоговые окна настройки печати и страницы
macOS предоставляет стандартные диалоговые окна настройки печати и страницы, которые могут отображаться в приложении, чтобы пользователи могли иметь согласованные возможности печати в каждом приложении, которое они используют.
В следующем коде показан стандартный диалог печати:
public bool ShowPrintAsSheet { get; set;} = true;
...
[Export ("showPrinter:")]
void ShowDocument (NSObject sender) {
var dlg = new NSPrintPanel();
// Display the print dialog as dialog box
if (ShowPrintAsSheet) {
dlg.BeginSheet(new NSPrintInfo(),this,this,null,new IntPtr());
} else {
if (dlg.RunModalWithPrintInfo(new NSPrintInfo()) == 1) {
var alert = new NSAlert () {
AlertStyle = NSAlertStyle.Critical,
InformativeText = "We need to print the document here...",
MessageText = "Print Document",
};
alert.RunModal ();
}
}
}
Если для свойства задано ShowPrintAsSheet
значение false
, запустите приложение и отобразите диалоговое окно печати, отобразится следующее:
Если для свойства задано ShowPrintAsSheet
значение true
, запустите приложение и отобразите диалоговое окно печати, отобразится следующее:
В следующем коде отобразится диалоговое окно макета страницы:
[Export ("showLayout:")]
void ShowLayout (NSObject sender) {
var dlg = new NSPageLayout();
// Display the print dialog as dialog box
if (ShowPrintAsSheet) {
dlg.BeginSheet (new NSPrintInfo (), this);
} else {
if (dlg.RunModal () == 1) {
var alert = new NSAlert () {
AlertStyle = NSAlertStyle.Critical,
InformativeText = "We need to print the document here...",
MessageText = "Print Document",
};
alert.RunModal ();
}
}
}
Если для свойства задано ShowPrintAsSheet
значение false
, запустите приложение и отобразите диалоговое окно макета печати, отобразится следующее:
Если для свойства задано ShowPrintAsSheet
значение true
, запустите приложение и отобразите диалоговое окно макета печати, отобразится следующее:
Дополнительные сведения о работе с диалогами настройки печати и страниц см. в документации apple NSPrintPanel и NSPageLayout .
Диалоговое окно сохранения
Диалоговое окно "Сохранить" предоставляет пользователям согласованный способ сохранения элемента в приложении.
В следующем коде отобразится стандартное диалоговое окно сохранения:
public bool ShowSaveAsSheet { get; set;} = true;
...
[Export("saveDocumentAs:")]
void ShowSaveAs (NSObject sender)
{
var dlg = new NSSavePanel ();
dlg.Title = "Save Text File";
dlg.AllowedFileTypes = new string[] { "txt", "html", "md", "css" };
if (ShowSaveAsSheet) {
dlg.BeginSheet(mainWindowController.Window,(result) => {
var alert = new NSAlert () {
AlertStyle = NSAlertStyle.Critical,
InformativeText = "We need to save the document here...",
MessageText = "Save Document",
};
alert.RunModal ();
});
} else {
if (dlg.RunModal () == 1) {
var alert = new NSAlert () {
AlertStyle = NSAlertStyle.Critical,
InformativeText = "We need to save the document here...",
MessageText = "Save Document",
};
alert.RunModal ();
}
}
}
Это AllowedFileTypes
строковый массив типов файлов, которые пользователь может выбрать, чтобы сохранить файл как. Тип файла можно указать как расширение или UTI. Значение по умолчанию — null
это значение, позволяющее использовать любой тип файла.
Если для свойства задано ShowSaveAsSheet
значение false
, запустите приложение и выберите "Сохранить как... " в меню "Файл ", отобразится следующее:
Пользователь может развернуть диалоговое окно:
Если для свойства задано ShowSaveAsSheet
значение true
, запустите приложение и выберите "Сохранить как... " в меню "Файл ", отобразится следующее:
Пользователь может развернуть диалоговое окно:
Дополнительные сведения о работе с диалоговым окном сохранения см. в документации Apple NSSavePanel .
Итоги
В этой статье подробно рассматривается работа с модальными окнами Windows, листами и стандартными системными диалоговых окнами в приложении Xamarin.Mac. Мы видели различные типы и использование модальных окон, листов и диалоговых окон, как создавать модальные окна и листы в построителе интерфейсов Xcode и как работать с модальными окнами, листами и диалогами в коде C#.