Diálogos en Xamarin.Mac
Al trabajar con C# y .NET en una aplicación de Xamarin.Mac, tiene acceso a los mismos diálogos y Windows modales que un desarrollador que trabaja en Objective-CObjective-C Dado que Xamarin.Mac se integra directamente con Xcode, puede usar el Interface Builder de Xcode para crear y mantener el Windows modal (u, opcionalmente, crearlos directamente en código de C#).
Aparece un cuadro de diálogo en respuesta a una acción del usuario y normalmente proporciona formas en que los usuarios pueden completar la acción. Un cuadro de diálogo requiere una respuesta del usuario antes de que se pueda cerrar.
Windows se puede usar en un estado Modeless (por ejemplo, un editor de texto que puede tener varios documentos abiertos a la vez) o Modal (por ejemplo, un cuadro de diálogo Exportar que se debe descartar antes de que la aplicación pueda continuar).
En este artículo, se tratarán los conceptos básicos de trabajar con diálogos y Windows modales en una aplicación de Xamarin.Mac. Se recomienda encarecidamente trabajar primero en el artículo Hola, Mac, en concreto en las secciones Introducción a Xcode y Interface Builder y Salidas y acciones, ya que trata los conceptos y técnicas clave que se usarán en este artículo.
Es posible que también quiera echar un vistazo a la sección del documento Aspectos internos de Exposing C# classes / methods to Objective-CExposing C# classes / methods to Objective-C donde se explican los comandos y que se usan para conectar las clases de C# a objetos y elementos de la interfaz de RegisterExportObjective-C usuario.
Introducción a los diálogos
Aparece un cuadro de diálogo en respuesta a una acción del usuario (por ejemplo, guardar un archivo) y proporciona una manera para que los usuarios completen esa acción. Un cuadro de diálogo requiere una respuesta del usuario antes de que se pueda cerrar.
Según Apple, hay tres maneras de presentar un diálogo:
- Modal del documento: un cuadro de diálogo modal de documento impide que el usuario haga cualquier otra cosa dentro de un documento determinado hasta que se descarte.
- Modal de aplicación: un cuadro de diálogo Modal de aplicación impide que el usuario interactúe con la aplicación hasta que se descarte.
- Modeless Un cuadro de diálogo modelado permite a los usuarios cambiar la configuración del cuadro de diálogo mientras siguen interactuando con la ventana del documento.
Ventana modal
Cualquier estándar NSWindow se puede usar como un cuadro de diálogo personalizado mostr guardarlo de forma modal:
Hojas de diálogo modales de documento
Una hoja es un cuadro de diálogo modal que se adjunta a una ventana de documento determinada, lo que impide que los usuarios interactúen con la ventana hasta que descartan el diálogo. Una hoja se adjunta a la ventana de la que emerge y solo se puede abrir una hoja para una ventana en cualquier momento.
Preferencias Windows
Una ventana de preferencias es un cuadro de diálogo no modelo que contiene la configuración de la aplicación que el usuario cambia con poca frecuencia. Las Windows suelen incluir una barra de herramientas que permite al usuario cambiar entre diferentes grupos de configuraciones:
Abrir cuadro de diálogo
El cuadro de diálogo Abrir proporciona a los usuarios una manera coherente de buscar y abrir un elemento en una aplicación:
Cuadros de diálogo imprimir y configurar páginas
macOS proporciona cuadros de diálogo estándar de instalación de impresión y página que la aplicación puede mostrar para que los usuarios puedan tener una experiencia de impresión coherente en cada aplicación que usen.
El cuadro de diálogo Imprimir se puede mostrar como un cuadro de diálogo flotante libre:
O bien, se puede mostrar como una hoja:
El cuadro de diálogo Configuración de página se puede mostrar como un cuadro de diálogo flotante gratuito:
O bien, se puede mostrar como una hoja:
Guardar diálogos
El cuadro de diálogo Guardar proporciona a los usuarios una manera coherente de guardar un elemento en una aplicación. El cuadro de diálogo Guardar tiene dos estados: Mínimo (también conocido como Contraído):
Y el estado Expandido:
El cuadro de diálogo Guardar mínimo también se puede mostrar como una hoja:
Al igual que el cuadro de diálogo Guardar expandido:
Para más información, consulte la sección Diálogos de las directrices de interfaz humana de OS X de Apple.
Agregar una ventana modal a un Project
Aparte de la ventana principal del documento, es posible que una aplicación de Xamarin.Mac tenga que mostrar otros tipos de ventanas al usuario, como Preferencias o Paneles de inspector.
Para agregar una nueva ventana, haga lo siguiente:
En la Explorador de soluciones, abra el archivo para editarlo en la página de Interface Builder Xcode.
Arrastre un nuevo controlador de vistas al Superficie de diseño:
En el Inspector de identidad,escriba para el nombre de clase:
Vuelva a Visual Studio para Mac, permita que se sincronice con Xcode y cree el
CustomDialogController.harchivo.Vuelva a Xcode y diseñe la interfaz:
Cree un segue modal desde la ventana principal de la aplicación al nuevo controlador de vistas arrastrando el control desde el elemento de la interfaz de usuario que abrirá el cuadro de diálogo a la ventana del cuadro de diálogo. Asigne el identificador :
Conectar todas las acciones ysalidas:
Guarde los cambios y vuelva a Visual Studio para Mac para sincronizar con Xcode.
Haga que CustomDialogController.cs el archivo sea parecido al siguiente:
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
}
}
Este código expone algunas propiedades para establecer el título y la descripción del diálogo y algunos eventos para reaccionar ante la cancelación o aceptación del diálogo.
A continuación, ViewController.cs edite el archivo, PrepareForSegue invalide el método y haga que sea parecido al siguiente:
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;
}
}
Este código inicializa el segue que definimos en el cuadro de diálogo Interface Builder Xcode y configura el título y la descripción. También controla la elección que el usuario realiza en el cuadro de diálogo.
Podemos ejecutar la aplicación y mostrar el cuadro de diálogo personalizado:
Para obtener más información sobre el uso de ventanas en una aplicación de Xamarin.Mac, consulte nuestra documentación sobre cómo trabajar Windows aplicación.
Crear una hoja personalizada
Una hoja es un cuadro de diálogo modal que se adjunta a una ventana de documento determinada, lo que impide que los usuarios interactúen con la ventana hasta que descartan el diálogo. Una hoja se adjunta a la ventana de la que emerge y solo se puede abrir una hoja para una ventana en cualquier momento.
Para crear una hoja personalizada en Xamarin.Mac, vamos a hacer lo siguiente:
En la Explorador de soluciones, abra el archivo para editarlo en la página de Interface Builder Xcode.
Arrastre un nuevo controlador de vistas al Superficie de diseño:
Diseñe la interfaz de usuario:
Cree un segue de hoja desde la ventana principal al nuevo controlador de vistas:
En el Inspector de identidad, asigne el nombre Clase del controlador de vista :
Defina las salidas y accionesnecesarias:
Guarde los cambios y vuelva a Visual Studio para Mac para sincronizar.
A continuación, SheetViewController.cs edite el archivo y haga que sea parecido al siguiente:
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
}
}
A continuación, ViewController.cs edite el archivo, PrepareForSegue edite el método y haga que sea parecido al siguiente:
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;
}
}
Si ejecutamos la aplicación y se abre la hoja, se adjuntará a la ventana:
Crear un cuadro de diálogo de preferencias
Antes de crear la vista de preferencias en Interface Builder, será necesario agregar un tipo de segue personalizado para controlar la conmutación de las preferencias. Agregue una nueva clase al proyecto y llámela ReplaceViewSeque . Edite la clase y haga que se parezca a la siguiente:
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
}
}
Una vez creado el segue personalizado, podemos agregar una nueva ventana en la página de Interface Builder Xcode para controlar nuestras preferencias.
Para agregar una nueva ventana, haga lo siguiente:
En la Explorador de soluciones, abra el archivo para editarlo en la página de Xcode Interface Builder.
Arrastre un nuevo controlador de ventana al Superficie de diseño:
Organice la ventana cerca del diseñador de la barra de menús:
Cree copias del controlador de vistas adjunto, ya que habrá pestañas en la vista de preferencias:
Arrastre un nuevo controlador de barra de herramientas desde la biblioteca:
Y suéltelo en la ventana de la Superficie de diseño:
Diseño del diseño de la barra de herramientas:
Control-Click y arrastre desde cada botón de la barra de herramientas hasta las vistas que creó anteriormente. Seleccione un tipo de segue personalizado:
Seleccione el nuevo Segue y establezca la clase en :
En el Diseñador de barras de menús de la Superficie de diseño, en el menú de la aplicación, seleccione Preferencias... , haga clic con el botón de control y arrástrelo a la ventana Preferencias para crear un segue Mostrar:
Guarde los cambios y vuelva a Visual Studio para Mac para sincronizar.
Si ejecutamos el código y seleccionamos preferencias... en el menú de laaplicación, se mostrará la ventana:
Para obtener más información sobre cómo trabajar con Windows y barras de herramientas, consulte nuestra documentación Windows y barras de herramientas.
Guardar y cargar preferencias
En una aplicación macOS típica, cuando el usuario realiza cambios en cualquiera de las preferencias de usuario de la aplicación, esos cambios se guardan automáticamente. La manera más fácil de controlar esto en una aplicación de Xamarin.Mac es crear una sola clase para administrar todas las preferencias del usuario y compartirla en todo el sistema.
En primer lugar, agregue AppPreferences una nueva clase al proyecto y herede de NSObject . Las preferencias se diseñarán para usar el enlace de datos y Key-Value codificación, lo que hará que el proceso de creación y mantenimiento de los formularios de preferencia sea mucho más sencillo. Dado que las preferencias contendrán una pequeña cantidad de tipos de datos simples, use el elemento integrado NSUserDefaults para almacenar y recuperar valores.
Edite AppPreferences.cs el archivo y haga que sea parecido al siguiente:
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 clase contiene algunas rutinas auxiliares como , , , , etc. para facilitar SaveIntLoadInt el SaveColorLoadColorNSUserDefaults trabajo. Además, dado que no tiene una manera integrada de controlar , los métodos y se usan para convertir colores NSUserDefaults en NSColorsNSColorToHexStringNSColorFromHexString cadenas hexadecimales basadas en web (donde #RRGGBBAA es la transparencia AA alfa) que se pueden almacenar y recuperar fácilmente.
En el AppDelegate.cs archivo , cree una instancia del objeto AppDelegate.cs que se usará en toda la aplicación:
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
...
Preferencias de cableado a vistas de preferencias
A continuación, conecte la clase Preference a los elementos de la interfaz de usuario en la ventana preferencia y las vistas creadas anteriormente. En Interface Builder, seleccione un controlador de vista de preferencias y cambie al Inspector de identidad,cree una clase personalizada para el controlador:
Vuelva a la Visual Studio para Mac sincronizar los cambios y abra la clase recién creada para su edición. Haga que la clase se parezca a la siguiente:
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 esta clase ha hecho dos cosas aquí: en primer lugar, hay una propiedad auxiliar para facilitar el acceso a AppApp En segundo lugar, Preferences la propiedad expone la clase Preferences global para el enlace de datos con cualquier control de interfaz de usuario colocado en esta vista.
A continuación, haga doble clic en el archivo Storyboard para volver a abrirlo en Interface Builder (y vea los cambios que se han realizado anteriormente). Arrastre los controles de interfaz de usuario necesarios para compilar la interfaz de preferencias en la vista. Para cada control, cambie al Inspector de enlace y enlace a las propiedades individuales de la clase AppPreference:
Repita los pasos anteriores para todos los paneles (controladores de vista) y Propiedades de preferencia necesarias.
Aplicar cambios de preferencia a todas las Windows
Como se indicó anteriormente, en una aplicación macOS típica, cuando el usuario realiza cambios en cualquiera de las preferencias de usuario de la aplicación, esos cambios se guardan automáticamente y se aplican a cualquier ventana que el usuario pueda tener abierta en la aplicación.
Una cuidadosa planeación y diseño de las preferencias y ventanas de la aplicación permitirá que este proceso se haga sin problemas y de forma transparente para el usuario final, con una cantidad mínima de trabajo de codificación.
Para cualquier ventana que consuma preferencias de aplicación, agregue la siguiente propiedad auxiliar a su controlador de vista de contenido para facilitar el acceso a AppDelegate:
#region Application Access
public static AppDelegate App {
get { return (AppDelegate)NSApplication.SharedApplication.Delegate; }
}
#endregion
A continuación, agregue una clase para configurar el contenido o el comportamiento en función de las preferencias del usuario:
public void ConfigureEditor() {
// General Preferences
TextEditor.AutomaticLinkDetectionEnabled = App.Preferences.SmartLinks;
TextEditor.AutomaticQuoteSubstitutionEnabled = App.Preferences.SmartQuotes;
...
}
Debe llamar al método de configuración cuando se abra la ventana por primera vez para asegurarse de que se ajusta a las preferencias del usuario:
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
// Configure editor from user preferences
ConfigureEditor ();
...
}
A continuación, AppDelegate.cs edite el archivo y agregue el método siguiente para aplicar los cambios de preferencia a todas las ventanas abiertas:
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 ();
}
}
}
A continuación, agregue PreferenceWindowDelegate una clase al proyecto y haga que se parezca a la siguiente:
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
}
}
Esto hará que los cambios de preferencia se envíen a todos los Windows cuando se cierre la ventana de preferencias.
Por último, edite el Controlador de ventana de preferencias y agregue el delegado creado anteriormente:
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
}
}
Con todos estos cambios en su lugar, si el usuario edita las preferencias de la aplicación y cierra la ventana preferencias, los cambios se aplicarán a todas las aplicaciones Windows:
Cuadro de diálogo Abrir
El cuadro de diálogo Abrir proporciona a los usuarios una manera coherente de buscar y abrir un elemento en una aplicación. Para mostrar un cuadro de diálogo abierto en una aplicación de Xamarin.Mac, use el código siguiente:
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;
}
}
En el código anterior, se abre una nueva ventana de documento para mostrar el contenido del archivo. Deberá reemplazar este código por la funcionalidad que requiere la aplicación.
Las siguientes propiedades están disponibles cuando se trabaja con NSOpenPanel :
- CanChooseFiles: si el usuario puede seleccionar archivos.
- CanChooseDirectories: si el usuario puede seleccionar directorios.
- AllowsMultipleSelection: si el usuario puede seleccionar más de un archivo a la vez.
- ResolveAliases: si selecciona y alias, lo resuelve en la ruta de acceso del archivo original.
- AllowedFileTypes: es una matriz de cadenas de tipos de archivo que el usuario puede seleccionar como una extensión o UTI. El valor predeterminado es
null, que permite abrir cualquier archivo.
El método muestra el cuadro de diálogo Abrir y permite al usuario seleccionar archivos o directorios (como especifican las propiedades) y devuelve si el usuario hace clic en RunModal ()1 el RunModal () Abrir.
El cuadro de diálogo Abrir devuelve los archivos o directorios seleccionados por el usuario como una matriz de direcciones URL en la URL propiedad .
Si ejecutamos el programa y seleccionamos el elemento Abrir... en el menú Archivo, se muestra lo siguiente:
Diálogos de instalación de impresión y página
macOS proporciona cuadros de diálogo estándar de instalación de impresión y página que la aplicación puede mostrar para que los usuarios puedan tener una experiencia de impresión coherente en cada aplicación que usen.
El código siguiente mostrará el cuadro de diálogo imprimir estándar:
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 ();
}
}
}
Si establecemos la propiedad en , ejecute la aplicación y muestre el cuadro de diálogo de impresión, se mostrará ShowPrintAsSheetfalse lo siguiente:
Si establece la propiedad en , ejecute la aplicación y muestre el cuadro de diálogo de impresión, se mostrará ShowPrintAsSheet lo true siguiente:
El código siguiente mostrará el cuadro de diálogo Diseño 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 ();
}
}
}
Si establecemos la propiedad en , ejecute la aplicación y muestre el cuadro de diálogo de diseño de impresión, se mostrará ShowPrintAsSheet lo false siguiente:
Si establece la ShowPrintAsSheet propiedad en , ejecute la aplicación y muestre el cuadro de diálogo de diseño de impresión, se mostrará lo true siguiente:
Para obtener más información sobre cómo trabajar con los diálogos de instalación de impresión y página, consulte la documentación de NSPrintPanel y NSPageLayout de Apple.
Cuadro de diálogo Guardar
El cuadro de diálogo Guardar proporciona a los usuarios una manera coherente de guardar un elemento en una aplicación.
El código siguiente mostrará el cuadro de diálogo Guardar estándar:
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 ();
}
}
}
La AllowedFileTypes propiedad es una matriz de cadenas de tipos de archivo que el usuario puede seleccionar para guardar el archivo. El tipo de archivo se puede especificar como una extensión o UTI. El valor predeterminado es null , que permite usar cualquier tipo de archivo.
Si establecemos la propiedad en , ejecute la aplicación y seleccione ShowSaveAsSheetfalse Guardar ShowSaveAsSheet el false Archivo, se mostrará lo siguiente:
El usuario puede expandir el cuadro de diálogo:
Si establecemos la propiedad en , ejecute la aplicación y seleccione ShowSaveAsSheettrue Guardar ShowSaveAsSheet el true Archivo, se mostrará lo siguiente:
El usuario puede expandir el cuadro de diálogo:
Para obtener más información sobre cómo trabajar con el cuadro de diálogo Guardar, consulte la documentación de NSSavePanel de Apple.
Resumen
En este artículo se ha realizado un análisis detallado del trabajo con modales Windows, hojas y los cuadros de diálogo estándar del sistema en una aplicación xamarin.mac. Vimos los diferentes tipos y usos de modales Windows, hojas y diálogos, cómo crear y mantener las hojas y Windows modales en el Interface Builder de Xcode y cómo trabajar con Windows modal, hojas y diálogos en código de C#.
Vínculos relacionados
- MacWindows (ejemplo)
- Hello, Mac
- Menús
- Windows
- Barras de herramientas
- OS X Human Interface Guidelines (Directrices de interfaz humana de OS X)
- Introducción a Windows
- Introducción a las hojas
- Introducción a la impresión


































