Dialogy v Xamarin.Macu
Při práci s C# a .NET v aplikaci Xamarin.Mac máte přístup ke stejným dialogovým oknům a modálním Windows jako vývojář pracující v aplikaci a Objective-CObjective-C Vzhledem k tomu, že Xamarin.Mac se integruje přímo s Xcode, můžete použít Interface Builder Xcode k vytvoření a údržbě modálního Windows (nebo je volitelně vytvořit přímo v kódu C#).
V reakci na akci uživatele se zobrazí dialogové okno, které obvykle uživatelům umožňuje akci dokončit. Dialogové okno vyžaduje odpověď od uživatele před jeho zavřením.
Windows lze použít v bezmodálním stavu (například v textovém editoru, který může mít najednou otevřených více dokumentů) nebo modální (například dialogové okno Export, které je nutné zavřít, aby aplikace pokračovala).
V tomto článku se budeme seznamovat se základy práce s dialogy a modálními Windows v aplikaci Xamarin.Mac. Důrazně doporučujeme, abyste si nejprve prošli článek Hello, Mac, konkrétně oddíly Úvod do Xcode a Interface Builder a Výstupy a Akce, protože se zabývá klíčovými koncepty a technikami, které budeme v tomto článku používat.
Možná se budete chtít podívat i na část dokumentu Exposing C# classes / methods to Objective-CExposing C# classes / methods to Objective-C která vysvětluje příkazy a používané k připojení tříd jazyka C# k objektům a prvkům uživatelského RegisterExportObjective-C rozhraní.
Úvod do dialogových oknů
Zobrazí se dialogové okno v reakci na akci uživatele (například uložení souboru) a poskytuje uživatelům způsob, jak ji dokončit. Dialogové okno vyžaduje odpověď od uživatele před jeho zavřením.
Podle společnosti Apple existují tři způsoby zobrazení dialogového okna:
- Modální dialogové okno dokumentu – Modální dialogové okno dokumentu brání uživateli v tom, aby v daném dokumentu dělal cokoli jiného, dokud se nezamítl.
- Modální dialogové okno aplikace – Modální dialogové okno brání uživateli v interakci s aplikací, dokud ji nezamítnou.
- Nemodální Ne moderování dialogového okna umožňuje uživatelům změnit nastavení v dialogovém okně a přitom stále pracovat s oknem dokumentu.
Modální okno
Jakýkoli standard NSWindow můžete použít jako přizpůsobené dialogové okno, které se zobrazí modálně:
Modální listy dialogového okna dokumentu
List je modální dialogové okno, které je připojené k danému oknu dokumentu a brání uživatelům v interakci s oknem, dokud dialogové okno nezamítnou. List je připojený k oknu, ze kterého se objevuje, a pro okno lze najednou otevřít pouze jeden list.
Předvolby Windows
Okno Předvolby je ne moderování dialogového okna, které obsahuje nastavení aplikace, která uživatel mění zřídka. Předvolby Windows často obsahují panel nástrojů, který uživateli umožňuje přepínat mezi různými skupinami nastavení:
Otevření dialogového okna
Otevřené dialogové okno poskytuje uživatelům konzistentní způsob, jak najít a otevřít položku v aplikaci:
Dialogová okna pro tisk a nastavení stránky
MacOS poskytuje standardní dialogová okna tiskových a stránkových nastavení, která může vaše aplikace zobrazit, aby uživatelé mohli mít konzistentní tisk v každé aplikaci, kterou používají.
Dialogové okno Tisk se může zobrazit jako bezplatné plovoucí dialogové okno:
Nebo se může zobrazit jako List:
Dialogové okno Vzhled stránky se může zobrazit jako bezplatné plovoucí dialogové okno:
Nebo se může zobrazit jako List:
Uložení dialogových oknů
Dialogové okno Uložit poskytuje uživatelům konzistentní způsob, jak uložit položku v aplikaci. Dialogové okno Uložit má dva stavy: Minimální (označuje se také jako Sbalené):
A rozbalený stav:
Dialogové okno Minimální uložení se také může zobrazit jako List:
Stejně jako v rozšířeném dialogovém okně Uložit:
Další informace najdete v části Dialogy v pokynech pro lidské rozhraní OS X společnosti Apple.
Přidání modálního okna do Project
Kromě hlavního okna dokumentu může aplikace Xamarin.Mac potřebovat zobrazit uživateli jiné typy oken, například Předvolby nebo Panely inspektoru.
Nové okno přidáte takto:
V Průzkumník řešeníotevřete soubor pro úpravy v souboru Xcode Interface Builder.
Přetáhněte nový kontroler zobrazení do Návrhová plocha:
V Identity Inspectoru zadejte jako Název třídy:
Přepněte zpět Visual Studio pro Mac, povolte jeho synchronizaci s Xcode a vytvořte
CustomDialogController.hsoubor.Vraťte se do Xcode a navrhovat rozhraní:
Přetahováním ovládacích prvků z prvku uživatelského rozhraní vytvořte modální segénu z hlavního okna aplikace do nového kontroleru zobrazení, který otevře dialogové okno dialogového okna. Přiřaďte identifikátor :
Připojení všech akcí avýstupů:
Uložte změny a vraťte se do Visual Studio pro Mac synchronizaci s Xcode.
Aby CustomDialogController.cs soubor vypadal takto:
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
}
}
Tento kód zpřístupňuje několik vlastností pro nastavení názvu a popisu dialogového okna a několik událostí, které reagují na zrušení nebo přijetí dialogového okna.
Dále upravte ViewController.cs soubor, přepište PrepareForSegue metodu a napište, aby vypadal takto:
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;
}
}
Tento kód inicializuje segu, kterou jsme definovali v Xcode Interface Builder našeho dialogového okna a nastaví název a popis. Zpracovává také výběr, který uživatel v dialogovém okně provede.
Můžeme spustit naši aplikaci a zobrazit vlastní dialogové okno:
Další informace o používání Windows v aplikaci Xamarin.Mac najdete v naší dokumentaci Práce Windows platformou.
Vytvoření vlastního listu
List je modální dialogové okno, které je připojené k danému oknu dokumentu a brání uživatelům v interakci s oknem, dokud dialogové okno nezamítnou. List je připojený k oknu, ze kterého se objevuje, a pro okno lze najednou otevřít pouze jeden list.
Pokud chcete vytvořit vlastní list v Xamarin.Macu, pustíme se do následujících kroků:
V Průzkumník řešeníotevřete soubor pro úpravy v souboru Xcode Interface Builder.
Přetáhněte nový kontroler zobrazení do Návrhová plocha:
Návrh uživatelského rozhraní:
Z hlavního okna vytvořte List Se do nového kontroleru zobrazení:
V Identity Inspectorupojmete třídu kontroleru zobrazení :
Definujte všechny potřebné výstupy aakce:
Uložte změny a vraťte se do Visual Studio pro Mac synchronizaci.
V dalším kroku upravte SheetViewController.cs soubor tak, aby vypadal takto:
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
}
}
Dále upravte ViewController.cs soubor, upravte PrepareForSegue metodu a vytvořte, aby vypadal takto:
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;
}
}
Pokud aplikaci spustíme a otevřeme List, připojí se k oknu:
Vytvoření dialogového okna předvoleb
Než rozložíme zobrazení předvoleb v Interface Builder, bude potřeba přidat vlastní typ přechod pro zpracování přecházení na Předvolby. Přidejte do projektu novou třídu a zavolejte ji ReplaceViewSeque . Upravte třídu a nastavte ji jako následující:
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
}
}
Když jste vytvořili vlastní přechod, můžeme do Interface Builder Xcodeu přidat nové okno pro zpracování našich předvoleb.
Chcete-li přidat nové okno, postupujte následovně:
V Průzkumník řešeníotevřete soubor pro úpravy v Interface Builder Xcode.
Přetáhněte nový kontroler oken do návrhová plocha:
Uspořádat okno poblíž návrháře panelu nabídek :
Vytvořte kopie připojeného kontroleru zobrazení tak, jak se budou v zobrazení předvoleb zobrazovat na kartách:
Přetáhněte nový kontroler panelu nástrojů z knihovny:
A přetáhněte ho do okna v Návrhová plocha:
Rozložení návrhu panelu nástrojů:
Control-Click a přetáhněte je z každého tlačítka panelu nástrojů na zobrazení, která jste vytvořili výše. Vyberte vlastní typ přechod:
Vyberte nový přechod a nastavte třídu na :
V Návrháři MenuBar na návrhová plocha vyberte v nabídce aplikace Předvolby..., ovládací prvek – klikněte a přetáhněte ho do okna Předvolby a vytvořte tak přechod zobrazení :
uložte změny a vraťte se do Visual Studio pro Mac k synchronizaci.
Pokud kód spouštíme a v nabídce aplikacevyberete Předvolby... , zobrazí se okno:
další informace o práci s Windows a panely nástrojů najdete v dokumentaci pro Windows a panely nástrojů .
Předvolby ukládání a načítání
Když uživatel provede v typické aplikaci macOS změny v kterékoli z uživatelských preferencí aplikace, tyto změny se automaticky uloží. Nejjednodušší způsob, jak to zpracovat v aplikaci Xamarin. Mac, je vytvořit jednu třídu, která bude spravovat všechny předvolby uživatele a sdílet je v celém systému.
Nejprve přidejte AppPreferences do projektu novou třídu a z ní dědit NSObject . Předvolby budou sloužit k použití datových vazeb a kódování Key-Value , což zajistí mnohem jednodušší proces vytváření a údržby formulářů předvoleb. Vzhledem k tomu, že se tyto preference skládají z malého množství jednoduchých typů dat, použijte vestavěnou aplikaci NSUserDefaults pro ukládání a načítání hodnot.
Upravte AppPreferences.cs soubor a nastavte jeho vzhled jako na následující:
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
}
}
Tato třída obsahuje několik pomocných rutin, jako například SaveInt , LoadInt , SaveColor , LoadColor , atd., aby bylo NSUserDefaults snazší pracovat. Kromě toho vzhledem k tomu, že nemá NSUserDefaults vestavěný způsob zpracování NSColors , NSColorToHexStringNSColorFromHexString metody a slouží k převodu barev na webové řetězce hex ( #RRGGBBAA kde AA je průhlednost alfa), které lze snadno uložit a načíst.
V AppDelegate.cs souboru vytvořte instanci objektu AppDelegate.cs , která bude použita pro celé aplikace:
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
...
Předvolby kabeláže do zobrazení předvoleb
Dále připojte třídu preference k prvkům uživatelského rozhraní v okně předvoleb a v zobrazeních, která jsou vytvořena výše. V Interface Builder vyberte kontroler zobrazení předvoleb a přepněte se na inspektora identity, vytvořte pro řadič vlastní třídu:
přepněte zpátky na Visual Studio pro Mac a synchronizujte změny a otevřete nově vytvořenou třídu pro úpravy. Nastavte, aby třída vypadala takto:
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
}
}
Všimněte si, že tato třída provedla dvě věci: Nejdřív je k dispozici pomocná App vlastnost, která usnadňuje přístup k App . Za druhé Preferences vlastnost zpřístupňuje globální třídu Preferences pro datovou vazbu s libovolnými ovládacími prvky uživatelského rozhraní umístěnými v tomto zobrazení.
Potom poklikejte na soubor scénáře a znovu ho otevřete v Interface Builder (a podívejte se na změny, které jste provedli výše). Přetáhněte jakékoli ovládací prvky uživatelského rozhraní potřebné k sestavení rozhraní předvoleb do zobrazení. Pro každý ovládací prvek přepněte na inspektor vazby a vytvořte vazbu na jednotlivé vlastnosti třídy AppPreference :
Opakujte výše uvedené kroky pro všechny panely (zobrazení řadičů) a požadované vlastnosti předvolby.
Použití změn předvoleb pro všechny otevřené Windows
Jak je uvedeno výše, v typické aplikaci macOS, když uživatel provede změny v kterékoli z uživatelských preferencí aplikace, tyto změny se uloží automaticky a uplatní se pro všechny uživatele, kteří v aplikaci můžou otevřít.
Pečlivé plánování a návrh předvoleb vaší aplikace a Windows umožní tomuto procesu hladce a transparentnímu uživateli, a to s minimálním množstvím práce s kódováním.
Pro všechna okna, která budou používat předvolby aplikace, přidejte následující vlastnost helper do svého kontroleru zobrazení obsahu, abyste měli přístup k našemu AppDelegateu snazší:
#region Application Access
public static AppDelegate App {
get { return (AppDelegate)NSApplication.SharedApplication.Delegate; }
}
#endregion
Dále přidejte třídu pro konfiguraci obsahu nebo chování na základě předvoleb uživatele:
public void ConfigureEditor() {
// General Preferences
TextEditor.AutomaticLinkDetectionEnabled = App.Preferences.SmartLinks;
TextEditor.AutomaticQuoteSubstitutionEnabled = App.Preferences.SmartQuotes;
...
}
Je nutné zavolat metodu konfigurace při prvním otevření okna, abyste se ujistili, že odpovídá předvolbám uživatele:
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
// Configure editor from user preferences
ConfigureEditor ();
...
}
V dalším kroku upravte AppDelegate.cs soubor a přidejte následující metodu, která aplikuje všechny změny předvoleb na všechna otevřená okna:
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 ();
}
}
}
Dále přidejte PreferenceWindowDelegate do projektu třídu a nastavte ji jako následující:
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
}
}
to způsobí, že se všechny změny předvoleb odešlou všem otevřeným Windows při zavření okna předvoleb.
Nakonec upravte kontroler okna předvoleb a přidejte delegáta, který jste vytvořili výše:
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
}
}
Pokud uživatel upraví předvolby aplikace a zavře okno předvoleb, budou tyto změny aplikovány na všechny otevřené Windows:
Dialogové okno otevřít
Dialogové okno otevřít poskytuje uživatelům konzistentní způsob, jak najít a otevřít položku v aplikaci. Chcete-li zobrazit otevřený dialog v aplikaci Xamarin. Mac, použijte následující kód:
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;
}
}
Ve výše uvedeném kódu otevíráme nové okno dokumentu, ve kterém se zobrazí obsah souboru. Tento kód budete muset nahradit funkcí, kterou vaše aplikace vyžaduje.
Následující vlastnosti jsou k dispozici při práci s NSOpenPanel :
- CanChooseFiles – Pokud uživatel může vybrat soubory.
- CanChooseDirectories – Pokud uživatel může vybírat adresáře.
- AllowsMultipleSelection – Pokud uživatel může současně vybrat více než jeden soubor.
- ResolveAliases – Pokud vyberete a alias, přeloží se na cestu k původnímu souboru.
- AllowedFileTypes – je pole řetězců typů souborů, které může uživatel vybrat buď jako rozšíření, nebo jako identifikátor UTI. Výchozí hodnota je
null, což umožňuje otevřít libovolný soubor.
RunModal ()Metoda zobrazí dialog Otevřít a umožní uživateli vybrat soubory nebo adresáře (podle zadání vlastností) a vrátí, 1 Pokud uživatel klikne na tlačítko RunModal () .
Dialogové okno otevřít vrátí vybrané soubory nebo adresáře uživatele jako pole adres URL ve URL Vlastnosti.
Pokud program spustíme a v nabídce soubor vyberte položku otevřít... , zobrazí se následující:
Dialogová okna Tisk a vzhled stránky
macOS poskytuje standardní dialogová okna pro tisk a stránku, které může vaše aplikace zobrazit, aby uživatelé mohli mít konzistentní možnosti tisku v každé aplikaci, kterou používají.
Následující kód zobrazí standardní dialogové okno Tisk:
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 ();
}
}
}
Pokud nastavíme ShowPrintAsSheet vlastnost na false , spustíte aplikaci a zobrazí se dialogové okno Tisk, zobrazí se následující:
Pokud nastavíte ShowPrintAsSheet vlastnost na true , spustíte aplikaci a zobrazí se dialogové okno Tisk, zobrazí se následující:
Následující kód zobrazí dialogové okno rozložení stránky:
[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 ();
}
}
}
Pokud nastavíme ShowPrintAsSheet vlastnost na false , spustíte aplikaci a zobrazí se dialogové okno rozložení tisku, zobrazí se následující:
Pokud nastavíte ShowPrintAsSheet vlastnost na true , spustíte aplikaci a zobrazí se dialogové okno rozložení tisku, zobrazí se následující:
Další informace o práci s dialogy tisk a nastavení stránky najdete v dokumentaci k NSPrintPanel a NSPageLayout společnosti Apple.
Dialogové okno Uložit
Dialogové okno Uložit poskytuje uživatelům konzistentní způsob, jak uložit položku v aplikaci.
Následující kód zobrazí standardní dialog Uložit:
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 ();
}
}
}
AllowedFileTypesVlastnost je pole řetězců typů souborů, které může uživatel vybrat k uložení souboru jako. Typ souboru může být buď zadaný jako příponový, nebo identifikátor UTI. Výchozí hodnota je null , která umožňuje použití libovolného typu souboru.
Pokud nastavíme vlastnost na , spustíme aplikaci a v nabídce Soubor vybereme Uložit jako, zobrazí ShowSaveAsSheetfalse se následující: ShowSaveAsSheetfalse
Uživatel může dialogové okno rozbalit:
Pokud nastavíme vlastnost na , spustíme aplikaci a v nabídce Soubor vybereme Uložit jako, zobrazí ShowSaveAsSheettrue se následující: ShowSaveAsSheettrue
Uživatel může dialogové okno rozbalit:
Další informace o práci s dialogem Uložit najdete v dokumentaci k objektu NSSavePanel společnosti Apple.
Souhrn
Tento článek podrobně popisuje práci s modálními Windows, listy a standardními systémovými dialogy v aplikaci Xamarin.Mac. Viděli jsme různé typy a použití modálních Windows, listů a dialogových oknů, jak vytvářet a udržovat modální Windows a listy v Interface Builder Xcode a jak pracovat s modálními Windows, listy a dialogy v kódu jazyka C#.


































