Caixas de diálogo no Xamarin.Mac
Ao trabalhar com C# e .NET em um aplicativo Xamarin.Mac, você tem acesso às mesmas Caixas de Diálogo e Janelas Modais que um desenvolvedor que trabalha e Objective-C o Xcode tem. Como o Xamarin.Mac se integra diretamente ao Xcode, você pode usar o Construtor de Interfaces do Xcode para criar e manter suas Janelas Modais (ou, opcionalmente, criá-las diretamente no código C#).
Uma caixa de diálogo é exibida em resposta a uma ação do usuário e normalmente fornece maneiras pelas quais os usuários podem concluir a ação. Uma caixa de diálogo requer uma resposta do usuário antes de ser fechada.
O Windows pode ser usado em um estado sem janela restrita (como um editor de texto que pode ter vários documentos abertos ao mesmo tempo) ou Modal (como uma caixa de diálogo Exportar que deve ser descartada antes que o aplicativo possa continuar).
Neste artigo, abordaremos as noções básicas de como trabalhar com Caixas de Diálogo e Janelas Modais em um aplicativo Xamarin.Mac. É altamente recomendável que você trabalhe primeiro no artigo Olá, Mac , especificamente nas seções Introdução ao Xcode e ao Construtor de Interfaces e Saídas e Ações , pois ele aborda os principais conceitos e técnicas que usaremos neste artigo.
Talvez você queira dar uma olhada na seção Expondo classes/métodos C# para Objective-Cdo documento Internos do Xamarin.Mac também, ele explica os Register
comandos e Export
usados para conectar suas classes C# a Objective-C objetos e elementos de interface do usuário.
Introdução às caixas de diálogo
Uma caixa de diálogo é exibida em resposta a uma ação do usuário (como salvar um arquivo) e fornece uma maneira de os usuários concluírem essa ação. Uma caixa de diálogo requer uma resposta do usuário antes de ser fechada.
De acordo com a Apple, existem três maneiras de apresentar um diálogo:
- Modal do documento - Uma caixa de diálogo Modal do documento impede que o usuário faça qualquer outra coisa em um determinado documento até que ele seja descartado.
- Modal do aplicativo - Uma caixa de diálogo Modal do aplicativo impede que o usuário interaja com o aplicativo até que ele seja descartado.
- Sem janela restrita Uma caixa de diálogo sem janela restrita permite que os usuários alterem as configurações na caixa de diálogo enquanto ainda interagem com a janela do documento.
Janela Modal
Qualquer padrão NSWindow
pode ser usado como uma caixa de diálogo personalizada, exibindo-o modalmente:
Folhas de diálogo modais do documento
Uma planilha é uma caixa de diálogo modal anexada a uma determinada janela de documento, impedindo que os usuários interajam com a janela até que ignorem a caixa de diálogo. Uma planilha é anexada à janela da qual ela emerge e somente uma planilha pode ser aberta para uma janela a qualquer momento.
Preferências Windows
Uma janela de preferências é uma caixa de diálogo sem janela restrita que contém as configurações do aplicativo que o usuário altera com pouca frequência. Preferências As janelas geralmente incluem uma barra de ferramentas que permite ao usuário alternar entre diferentes grupos de configurações:
Abrir caixa de diálogo
A caixa de diálogo Abrir oferece aos usuários uma maneira consistente de localizar e abrir um item em um aplicativo:
Caixas de diálogo de impressão e configuração de página
O macOS fornece caixas de diálogo padrão de impressão e configuração de página que seu aplicativo pode exibir para que os usuários possam ter uma experiência de impressão consistente em todos os aplicativos que usam.
A caixa de diálogo Imprimir pode ser exibida como uma caixa de diálogo flutuante livre:
Ou pode ser exibido como uma planilha:
A caixa de diálogo Configurar página pode ser exibida como uma caixa de diálogo flutuante livre:
Ou pode ser exibido como uma planilha:
Salvar caixas de diálogo
A caixa de diálogo Salvar oferece aos usuários uma maneira consistente de salvar um item em um aplicativo. A caixa de diálogo Salvar tem dois estados: Mínimo (também conhecido como Collapsed):
E o estado expandido :
A caixa de diálogo Salvar mínimo também pode ser exibida como uma planilha:
Assim como a caixa de diálogo Salvar expandida :
Para obter mais informações, consulte a seção Diálogos das Diretrizes de Interface Humana do OS X da Apple
Adicionando uma janela modal a um projeto
Além da janela principal do documento, um aplicativo Xamarin.Mac pode precisar exibir outros tipos de janelas para o usuário, como Preferências ou Painéis de Inspetor.
Para adicionar uma nova janela, faça o seguinte:
No Gerenciador de Soluções, abra o
Main.storyboard
arquivo para edição no Construtor de Interfaces do Xcode.Arraste um novo Controlador de Exibição para a Superfície de Design:
No Inspetor de identidade, insira
CustomDialogController
para o Nome da classe:Volte para o Visual Studio para Mac, permita que ele seja sincronizado com o Xcode e crie o
CustomDialogController.h
arquivo.Retorne ao Xcode e projete sua interface:
Crie um Modal Segue da Janela Principal do seu aplicativo para o novo Controlador de Exibição arrastando com a tecla Control pressionada do elemento de interface do usuário que abrirá a caixa de diálogo para a janela da caixa de diálogo. Atribua o identificador
ModalSegue
:Conecte todas as ações e tomadas:
Salve suas alterações e retorne ao Visual Studio para Mac para sincronizar com o Xcode.
Faça com que o CustomDialogController.cs
arquivo tenha a seguinte aparência:
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
}
}
Esse código expõe algumas propriedades para definir o título e a descrição da caixa de diálogo e alguns eventos para reagir à caixa de diálogo que está sendo cancelada ou aceita.
Em seguida, edite o ViewController.cs
arquivo, substitua o PrepareForSegue
método e faça com que ele se pareça com o seguinte:
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;
}
}
Esse código inicializa o segue que definimos no Construtor de Interfaces do Xcode para nossa caixa de diálogo e configura o título e a descrição. Ele também lida com a escolha que o usuário faz na caixa de diálogo.
Podemos executar nosso aplicativo e exibir a caixa de diálogo personalizada:
Para obter mais informações sobre como usar o Windows em um aplicativo Xamarin.Mac, consulte nossa documentação Trabalhando com o Windows .
Criando uma planilha personalizada
Uma planilha é uma caixa de diálogo modal anexada a uma determinada janela de documento, impedindo que os usuários interajam com a janela até que ignorem a caixa de diálogo. Uma planilha é anexada à janela da qual ela emerge e somente uma planilha pode ser aberta para uma janela a qualquer momento.
Para criar uma planilha personalizada no Xamarin.Mac, vamos fazer o seguinte:
No Gerenciador de Soluções, abra o
Main.storyboard
arquivo para edição no Construtor de Interfaces do Xcode.Arraste um novo Controlador de Exibição para a Superfície de Design:
Projete sua interface de usuário:
Crie um Sheet Segue da janela principal para o novo View Controller:
No Inspetor de identidade, nomeie a classe
SheetViewController
do controlador de exibição :Defina quaisquer saídas e ações necessárias:
Salve suas alterações e retorne ao Visual Studio para Mac para sincronizar.
Em seguida, edite o SheetViewController.cs
arquivo e faça com que ele fique parecido com o seguinte:
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
}
}
Em seguida, edite o ViewController.cs
arquivo, edite o PrepareForSegue
método e faça com que ele fique parecido com o seguinte:
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;
}
}
Se executarmos nosso aplicativo e abrirmos a planilha, ela será anexada à janela:
Criando uma caixa de diálogo de preferências
Antes de definirmos o Modo de Exibição de Preferências no Construtor de Interfaces, precisaremos adicionar um tipo de segue personalizado para lidar com a troca das preferências. Adicione uma nova classe ao seu projeto e chame-a ReplaceViewSeque
de . Edite a classe e faça com que ela fique parecida com a seguinte:
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
}
}
Com o segue personalizado criado, podemos adicionar uma nova janela no Construtor de Interfaces do Xcode para lidar com nossas preferências.
Para adicionar uma nova janela, faça o seguinte:
No Gerenciador de Soluções, abra o
Main.storyboard
arquivo para edição no Construtor de Interfaces do Xcode.Arraste um novo Controlador de Janela para a Superfície de Design:
Organize a janela perto do designer da barra de menus:
Crie cópias do Controlador de Exibição anexado, pois haverá guias em seu modo de exibição de preferência:
Arraste um novo Controlador da Barra de Ferramentas da Biblioteca:
E solte-o na Janela na Superfície de Design:
Faça o layout do design da sua barra de ferramentas:
Clique com a tecla Control pressionada e arraste de cada botão da barra de ferramentas para as exibições criadas acima. Selecione um tipo de segue personalizado :
Selecione o novo Segue e defina a Classe como
ReplaceViewSegue
:No Designer da Barra de Menus na Superfície de Design, no Menu do Aplicativo, selecione Preferências..., clique com a tecla Control pressionada e arraste para a Janela de Preferências para criar um Show segue:
Salve suas alterações e retorne ao Visual Studio para Mac para sincronizar.
Se executarmos o código e selecionarmos as Preferências... no Menu do Aplicativo, a janela será exibida:
Para obter mais informações sobre como trabalhar com o Windows e as Barras de Ferramentas, consulte nossa documentação do Windows e das Barras de Ferramentas.
Salvando e carregando preferências
Em um aplicativo macOS típico, quando o usuário faz alterações em qualquer uma das preferências do usuário do aplicativo, essas alterações são salvas automaticamente. A maneira mais fácil de lidar com isso em um aplicativo Xamarin.Mac é criar uma única classe para gerenciar todas as preferências do usuário e compartilhá-la em todo o sistema.
Primeiro, adicione uma nova AppPreferences
classe ao projeto e herde de NSObject
. As preferências serão projetadas para usar a vinculação de dados e a codificação de valor-chave, o que tornará o processo de criação e manutenção dos formulários de preferência muito mais simples. Como as Preferências consistirão em uma pequena quantidade de tipos de dados simples, use o interno NSUserDefaults
para armazenar e recuperar valores.
Edite o AppPreferences.cs
arquivo e faça com que ele fique parecido com o seguinte:
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
}
}
Essa classe contém algumas rotinas auxiliares, como SaveInt
, LoadInt
, SaveColor
, LoadColor
, etc. para facilitar o trabalho NSUserDefaults
. Além disso, como NSUserDefaults
não possui uma maneira integrada de lidar com NSColors
, os NSColorToHexString
métodos and NSColorFromHexString
são usados para converter cores em strings hexadecimais baseadas na web (#RRGGBBAA
onde AA
está a transparência alfa) que podem ser facilmente armazenadas e recuperadas.
No arquivo, crie uma instância do objeto AppPreferences que será usada em todo o AppDelegate.cs
aplicativo:
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
...
Preferências de fiação para vistas de preferência
Em seguida, conecte a classe Preference aos elementos da interface do usuário na janela de preferências e nas exibições criadas acima. No Construtor de Interfaces, selecione um Controlador de Exibição de Preferências e alterne para o Inspetor de Identidade, crie uma classe personalizada para o controlador:
Volte para o Visual Studio para Mac para sincronizar suas alterações e abrir a classe recém-criada para edição. Faça com que a classe se pareça com a seguinte:
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
}
}
Observe que essa classe fez duas coisas aqui: Primeiro, há uma propriedade auxiliar App
para facilitar o acesso ao AppDelegate . Em segundo lugar, a Preferences
propriedade expõe a classe AppPreferences global para associação de dados com todos os controles de interface do usuário colocados nesse modo de exibição.
Em seguida, clique duas vezes no arquivo Storyboard para reabri-lo no Construtor de Interfaces (e veja as alterações feitas acima). Arraste todos os controles de interface do usuário necessários para criar a interface de preferências para a Exibição. Para cada controle, alterne para o Inspetor de Associação e vincule às propriedades individuais da classe AppPreference :
Repita as etapas acima para todos os painéis (Controladores de vista) e Propriedades de preferência necessárias.
Aplicando alterações de preferência a todas as janelas abertas
Conforme mencionado acima, em um aplicativo macOS típico, quando o usuário faz alterações em qualquer uma das Preferências do Usuário do Aplicativo, essas alterações são salvas automaticamente e aplicadas a qualquer janela que o usuário possa ter aberto no aplicativo.
O planejamento e o design cuidadosos das preferências e janelas do seu aplicativo permitirão que esse processo aconteça de forma suave e transparente para o usuário final, com uma quantidade mínima de trabalho de codificação.
Para qualquer Window que consumirá Preferências do Aplicativo, adicione a seguinte propriedade auxiliar ao seu Controlador de Exibição de Conteúdo para facilitar o acesso ao nosso AppDelegate :
#region Application Access
public static AppDelegate App {
get { return (AppDelegate)NSApplication.SharedApplication.Delegate; }
}
#endregion
Em seguida, adicione uma classe para configurar o conteúdo ou o comportamento com base nas preferências do usuário:
public void ConfigureEditor() {
// General Preferences
TextEditor.AutomaticLinkDetectionEnabled = App.Preferences.SmartLinks;
TextEditor.AutomaticQuoteSubstitutionEnabled = App.Preferences.SmartQuotes;
...
}
Você precisa chamar o método de configuração quando a janela é aberta pela primeira vez para garantir que ela esteja em conformidade com as preferências do usuário:
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
// Configure editor from user preferences
ConfigureEditor ();
...
}
Em seguida, edite o AppDelegate.cs
arquivo e adicione o seguinte método para aplicar quaisquer alterações de preferência a todas as janelas abertas:
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 ();
}
}
}
Em seguida, adicione uma PreferenceWindowDelegate
classe ao projeto e faça com que ela tenha a seguinte aparência:
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
}
}
Isso fará com que todas as alterações de preferência sejam enviadas para todas as janelas abertas quando a janela de preferências for fechada.
Por fim, edite o Controlador de Janela de Preferências e adicione o delegado criado acima:
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
}
}
Com todas essas alterações em vigor, se o usuário editar as Preferências do aplicativo e fechar a janela de preferências, as alterações serão aplicadas a todas as janelas abertas:
A caixa de diálogo Abrir
A caixa de diálogo Abrir oferece aos usuários uma maneira consistente de localizar e abrir um item em um aplicativo. Para exibir uma caixa de diálogo Abrir em um aplicativo Xamarin.Mac, use o seguinte código:
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;
}
}
No código acima, estamos abrindo uma nova janela de documento para exibir o conteúdo do arquivo. Você precisará substituir esse código pela funcionalidade exigida pelo seu aplicativo.
As seguintes propriedades estão disponíveis ao trabalhar com um NSOpenPanel
:
- CanChooseFiles - Se
true
o usuário puder selecionar arquivos. - CanChooseDirectories - Se
true
o usuário puder selecionar diretórios. - AllowsMultipleSelection - Se
true
o usuário puder selecionar mais de um arquivo por vez. - ResolveAliases - Se
true
selecionar e alias, resolve-o para o caminho do arquivo original. - AllowedFileTypes - É uma matriz de cadeia de caracteres de tipos de arquivo que o usuário pode selecionar como uma extensão ou UTI. O valor padrão é
null
, que permite que qualquer arquivo seja aberto.
O RunModal ()
método exibe a caixa de diálogo Abrir e permite que o usuário selecione arquivos ou diretórios (conforme especificado pelas propriedades) e retorna 1
se o usuário clicar no botão Abrir .
A caixa de diálogo Abrir retorna os arquivos ou diretórios selecionados do usuário como uma matriz de URLs na URL
propriedade.
Se executarmos o programa e selecionarmos o item Abrir... no menu Arquivo, o seguinte será exibido:
As caixas de diálogo Imprimir e Configurar página
O macOS fornece caixas de diálogo padrão de impressão e configuração de página que seu aplicativo pode exibir para que os usuários possam ter uma experiência de impressão consistente em todos os aplicativos que usam.
O código a seguir mostrará a caixa de diálogo de impressão padrão:
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 ();
}
}
}
Se definirmos a ShowPrintAsSheet
propriedade como false
, executar o aplicativo e exibir a caixa de diálogo de impressão, o seguinte será exibido:
Se definir a ShowPrintAsSheet
propriedade como true
, execute o aplicativo e exiba a caixa de diálogo de impressão, o seguinte será exibido:
O código a seguir exibirá a caixa de diálogo Layout de página:
[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 ();
}
}
}
Se definirmos a ShowPrintAsSheet
propriedade como false
, executar o aplicativo e exibir a caixa de diálogo de layout de impressão, o seguinte será exibido:
Se definir a ShowPrintAsSheet
propriedade como true
, execute o aplicativo e exiba a caixa de diálogo de layout de impressão, o seguinte será exibido:
Para obter mais informações sobre como trabalhar com as caixas de diálogo de impressão e configuração de página, consulte a documentação NSPrintPanel e NSPageLayout da Apple.
A caixa de diálogo Salvar
A caixa de diálogo Salvar oferece aos usuários uma maneira consistente de salvar um item em um aplicativo.
O código a seguir mostrará a caixa de diálogo Salvar padrão:
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 ();
}
}
}
A AllowedFileTypes
propriedade é uma matriz de cadeia de caracteres de tipos de arquivo que o usuário pode selecionar para salvar o arquivo. O tipo de arquivo pode ser especificado como uma extensão ou UTI. O valor padrão é null
, que permite que qualquer tipo de arquivo seja usado.
Se definirmos a ShowSaveAsSheet
propriedade como false
, execute o aplicativo e selecione Salvar como... no menu Arquivo, o seguinte será exibido:
O usuário pode expandir a caixa de diálogo:
Se definirmos a ShowSaveAsSheet
propriedade como true
, execute o aplicativo e selecione Salvar como... no menu Arquivo, o seguinte será exibido:
O usuário pode expandir a caixa de diálogo:
Para obter mais informações sobre como trabalhar com a caixa de diálogo Salvar, consulte a documentação NSSavePanel da Apple.
Resumo
Este artigo examinou detalhadamente o trabalho com janelas modais, planilhas e caixas de diálogo do sistema padrão em um aplicativo Xamarin.Mac. Vimos os diferentes tipos e usos de Janelas Modais , Planilhas e Caixas de Diálogo, como criar e manter Janelas Modais e Planilhas no Construtor de Interfaces do Xcode e como trabalhar com Janelas Modais