Diálogos 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 trabalhando e Objective-CXcode faz. Como o Xamarin.Mac se integra diretamente ao Xcode, você pode usar o Construtor de Interfaces do Xcode para criar e manter seu Windows Modal (ou, opcionalmente, criá-los diretamente no código C#).
Uma caixa de diálogo aparece 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 Modeless (como um editor de texto que pode ter vários documentos abertos ao mesmo tempo) ou Modal (como uma caixa de diálogo Export que deve ser descartada antes que o aplicativo possa continuar).
Neste artigo, abordaremos os conceitos básicos 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 Interface e Saídas e Ações, pois ele aborda os principais conceitos e técnicas que usaremos neste artigo.
Você pode querer dar uma olhada na seção Expondo classes C# / métodos para Objective-C do documento Xamarin.Mac Internals também, ele explica os Register
comandos e Export
usados para conectar suas classes C# a Objective-C objetos e elementos da interface do usuário.
Introdução às caixas de diálogo
Uma caixa de diálogo aparece em resposta a uma ação do usuário (como salvar um arquivo) e fornece uma maneira para 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 Dialog:
- Modal de Documento - Uma caixa de diálogo Modal de Documento impede que o usuário faça qualquer outra coisa dentro de um determinado documento até que ele seja descartado.
- Modal de aplicativo - Uma caixa de diálogo modal de aplicativo impede que o usuário interaja com o aplicativo até que ele seja descartado.
- Sem moderação Uma caixa de diálogo sem moderação 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-a modalmente:
Folhas de diálogo modais de 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 descartem a caixa de diálogo. Uma folha é anexada à janela da qual ela emerge e apenas uma folha pode ser aberta para uma janela a qualquer momento.
Preferências do 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 O Windows geralmente inclui 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 Recolhido):
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 do 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 View Controller para a superfície de design:
No Inspetor de Identidade, insira
CustomDialogController
o Nome da classe:Volte para o Visual Studio para Mac, permita que ele sincronize 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 o controle do elemento da interface do usuário que abrirá a caixa de diálogo para a janela da caixa de diálogo. Atribua o identificador
ModalSegue
:Conecte quaisquer ações e saídas:
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 tenha a seguinte aparência:
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 a sequência que definimos no Construtor de Interface do Xcode em 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 descartem a caixa de diálogo. Uma folha é anexada à janela da qual ela emerge e apenas uma folha 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 View Controller para a superfície de design:
Projete sua interface de usuário:
Crie um Sheet Segue da sua janela principal para o novo View Controller:
No Inspetor de Identidade, nomeie a classe
SheetViewController
do controlador de exibição:Defina as 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 torne-o 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 tenha a seguinte aparência:
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 a Visualização de Preferências no Construtor de Interfaces, precisaremos adicionar um tipo de opção personalizado para lidar com a alternância das preferências. Adicione uma nova classe ao seu projeto e chame-a ReplaceViewSeque
de . Edite a classe e faça com que ela tenha a seguinte aparência:
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 acompanhamento personalizado criado, podemos adicionar uma nova janela no Construtor de Interface 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 View Controller anexado, pois haverá guias em sua visualização de preferência:
Arraste um novo controlador de barra de ferramentas da biblioteca:
E solte-o na janela na superfície de design:
Layout do design da barra de ferramentas:
Clique com a tecla Control pressionada e arraste de cada botão da barra de ferramentas para os modos de exibição criados 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 até 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.
Preferências de salvamento e carregamento
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 do NSObject
. As preferências serão projetadas para usar Vinculação de Dados e Codificação de Chave-Valor , 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 NSUserDefaults
uma pequena quantidade de tipos de dados simples, use o interno para armazenar e recuperar valores.
Edite o AppPreferences.cs
arquivo e faça com que ele tenha a seguinte aparência:
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
}
}
Esta classe contém algumas rotinas auxiliares, como SaveInt
, LoadInt
, SaveColor
, LoadColor
, etc. para facilitar o trabalho NSUserDefaults
. Além disso, como NSUserDefaults
não tem uma maneira interna de lidar com NSColors
, os NSColorToHexString
métodos e NSColorFromHexString
são usados para converter cores em cadeias de caracteres 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á usado 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 modos de exibição de preferência
Em seguida, conecte a classe Preference aos elementos da interface do usuário na Janela de Preferência e nas Exibições criadas acima. No Construtor de Interfaces, selecione um Controlador de Exibição de Preferência e alterne para o Inspetor de Identidade, crie uma classe personalizada para o controlador:
Alterne de volta 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 tenha a seguinte aparência:
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 vinculação de dados com quaisquer controles de interface do usuário colocados neste View.
Em seguida, clique duas vezes no arquivo Storyboard para reabri-lo no Interface Builder (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 Binding Inspector e vincule às propriedades individuais da classe AppPreference :
Repita as etapas acima para todos os painéis (Exibir controladores) e Propriedades de preferência necessárias.
Aplicando alterações de preferência a todas as janelas abertas
Como dito 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 Janela que consumirá as Preferências do Aplicativo, adicione a seguinte propriedade auxiliar ao 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 de acordo 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 ele 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 quaisquer alterações de preferência sejam enviadas para todos os Windows abertos quando a janela de preferência for fechada.
Finalmente, edite o Controlador da 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
estiver selecionando 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 como. 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 do NSSavePanel da Apple.
Resumo
Este artigo deu uma olhada detalhada no trabalho com o Windows Modal, Planilhas e as caixas de diálogo padrão do sistema em um aplicativo Xamarin.Mac. Vimos os diferentes tipos e usos de Modal Windows, Sheets e Dialogs, como criar e manter Modal Windows e Sheets no Construtor de Interfaces do Xcode e como trabalhar com Modal Windows, Sheets e Dialogs em código C#.