Windows in Xamarin.Mac

Questo articolo illustra l'uso di finestre e pannelli in un'applicazione Xamarin.Mac. Descrive la creazione di finestre e pannelli in Xcode e Interface Builder, il caricamento da storyboard e file xib e l'uso a livello di codice.

Quando si lavora con C# e .NET in un'applicazione Xamarin.Mac, è possibile accedere agli stessi pannelli e Windows che uno sviluppatore lavora in Objective-C e Xcode . Poiché Xamarin.Mac si integra direttamente con Xcode, è possibile usare Interface Builder di Xcode per creare e gestire Windows e Pannelli (o facoltativamente crearli direttamente nel codice C#).

In base allo scopo, un'applicazione Xamarin.Mac può presentare una o più finestre sullo schermo per gestire e coordinare le informazioni visualizzate e funzionanti. Le funzioni principali di una finestra sono:

  1. Per fornire un'area in cui è possibile posizionare e gestire visualizzazioni e controlli.
  2. Per accettare e rispondere agli eventi in risposta all'interazione dell'utente con la tastiera e il mouse.

Windows può essere usato in uno stato modeless (ad esempio un editor di testo che può avere più documenti aperti contemporaneamente) o modale (ad esempio una finestra di dialogo di esportazione che deve essere ignorata prima che l'applicazione possa continuare).

I pannelli sono un tipo speciale di Window (una sottoclasse della classe base NSWindow ), che in genere servono una funzione ausiliaria in un'applicazione, ad esempio finestre di utilità come Controlli formato testo e Selezione colori di sistema.

Editing a window in Xcode

In questo articolo verranno illustrate le nozioni di base sull'uso di Windows e Pannelli in un'applicazione Xamarin.Mac. È consigliabile usare prima di tutto l'articolo Hello, Mac , in particolare le sezioni Introduzione a Xcode e Interface Builder e Outlet e Actions , in quanto illustra i concetti e le tecniche chiave che verranno usati in questo articolo.

È possibile esaminare anche la sezione Esposizione di classi/metodi C# alObjective-Cdocumento Internals di Xamarin.Mac, che illustra anche i Register comandi e Export usati per collegare le classi C# agli oggetti e agli Objective-C elementi dell'interfaccia utente.

Introduzione alle finestre

Come indicato in precedenza, una finestra fornisce un'area in cui le visualizzazioni e i controlli possono essere posizionati e gestiti e rispondono agli eventi in base all'interazione dell'utente (tramite tastiera o mouse).

Secondo Apple, esistono cinque tipi principali di Windows in un'app macOS:

  • Finestra documento: una finestra del documento contiene dati utente basati su file, ad esempio un foglio di calcolo o un documento di testo.
  • Finestra dell'app: una finestra dell'app è la finestra principale di un'applicazione non basata su documenti, ad esempio l'app Calendario in un Mac.
  • Pannello : un pannello si allinea sopra altre finestre e fornisce strumenti o controlli che gli utenti possono usare durante l'apertura dei documenti. In alcuni casi, un pannello può essere traslucente (ad esempio quando si lavora con elementi grafici di grandi dimensioni).
  • Finestra di dialogo : viene visualizzata una finestra di dialogo in risposta a un'azione dell'utente e in genere fornisce i modi in cui gli utenti possono completare l'azione. Una finestra di dialogo richiede una risposta dell'utente prima che possa essere chiusa. (Vedere Uso dei dialoghi)
  • Avvisi : un avviso è un tipo speciale di finestra di dialogo che viene visualizzato quando si verifica un problema grave (ad esempio un errore) o come avviso ,ad esempio la preparazione all'eliminazione di un file. Poiché un avviso è una finestra di dialogo, richiede anche una risposta dell'utente prima che possa essere chiusa. (Vedere Uso degli avvisi)

Per altre informazioni, vedere la sezione Informazioni su Windows dei temi di progettazione macOS di Apple.

Finestre principali, chiave e inattive

Windows in un'applicazione Xamarin.Mac può apparire e comportarsi in modo diverso in base al modo in cui l'utente interagisce attualmente con loro. La finestra principale del documento o dell'app attualmente incentrata sull'attenzione dell'utente è detta finestra principale. Nella maggior parte dei casi questa finestra sarà anche la finestra chiave (la finestra che attualmente accetta l'input dell'utente). Ma questo non è sempre il caso, ad esempio, una selezione colori potrebbe essere aperta e essere la finestra Chiave con cui l'utente interagisce per modificare lo stato di un elemento nella finestra documento (che sarebbe ancora la finestra principale).

Le finestre principali e chiave (se separate) sono sempre attive, Le finestre inattive sono finestre aperte che non sono in primo piano. Ad esempio, un'applicazione editor di testo potrebbe avere più documenti aperti alla volta, solo la finestra principale sarà attiva, tutte le altre saranno inattive.

Per altre informazioni, vedere la sezione Informazioni su Windows dei temi di progettazione macOS di Apple.

Finestre di denominazione

Una finestra può visualizzare una barra del titolo e, quando viene visualizzato il titolo, in genere è il nome dell'applicazione, il nome del documento su cui si sta lavorando o la funzione della finestra( ad esempio Inspector). Alcune applicazioni non visualizzano una barra del titolo perché sono riconoscibili per vista e non funzionano con i documenti.

Apple suggerisce le linee guida seguenti:

  • Usare il nome dell'applicazione per il titolo di una finestra principale non documento.
  • Assegnare un nome a una nuova finestra untitleddel documento. Per il primo nuovo documento, non aggiungere un numero al titolo , ad esempio untitled 1. Se l'utente crea un altro nuovo documento prima di salvare e stlare il primo, chiamare tale finestra untitled 2, untitled 3e così via.

Per altre informazioni, vedere la sezione Denominazione di Windows dei temi di progettazione macOS di Apple.

Finestre a schermo intero

In macOS la finestra di un'applicazione può nascondere tutto ciò che include la barra dei menu dell'applicazione (che può essere visualizzata spostando il cursore nella parte superiore dello schermo) per fornire un'interazione senza distrazioni con il contenuto.

Apple suggerisce le linee guida seguenti:

  • Determinare se è opportuno che una finestra vada a schermo intero. Le applicazioni che forniscono brevi interazioni (ad esempio un calcolatore) non devono fornire una modalità schermo intero.
  • Mostra la barra degli strumenti se l'attività a schermo intero lo richiede. In genere la barra degli strumenti è nascosta in modalità schermo intero.
  • La finestra a schermo intero deve avere tutte le funzionalità che gli utenti devono completare l'attività.
  • Se possibile, evitare l'interazione del Finder mentre l'utente si trova in una finestra a schermo intero.
  • Sfruttare lo spazio dello schermo aumentato senza spostare lo stato attivo dall'attività principale.

Per altre informazioni, vedere la sezione Windows a schermo intero dei temi di progettazione macOS di Apple.

Pannelli

Un pannello è una finestra ausiliaria che contiene controlli e opzioni che influiscono sul documento attivo o sulla selezione (ad esempio, selezione colori di sistema):

A color panel

I pannelli possono essere specifici dell'app o a livello di sistema. I pannelli specifici dell'app passano sopra la parte superiore delle finestre dei documenti dell'applicazione e scompaiono quando l'applicazione è in background. Pannelli a livello di sistema (ad esempio il pannello Tipi di carattere ), float sopra tutte le finestre aperte indipendentemente dall'applicazione.

Apple suggerisce le linee guida seguenti:

  • In generale, usare un pannello standard, i pannelli trasparenti devono essere usati solo con moderazione e per le attività a elevato utilizzo grafico.
  • È consigliabile usare un pannello per consentire agli utenti di accedere facilmente a controlli o informazioni importanti che influiscono direttamente sull'attività.
  • Nascondere e visualizzare i pannelli in base alle esigenze.
  • I pannelli devono includere sempre la barra del titolo.
  • I pannelli non devono includere un pulsante a icona attivo.

Ispettori

La maggior parte delle applicazioni macOS moderne presenta controlli ausiliari e opzioni che influiscono sul documento attivo o sulla selezione come Controlli che fanno parte della finestra principale (come l'app Pages mostrata di seguito), anziché usare Panel Windows:

An example inspector

Per altre informazioni, vedere la sezione Pannelli dei temi di progettazione macOS di Apple e l'app di esempio MacInspector per un'implementazione completa di un'interfaccia Inspector in un'app Xamarin.Mac.

Creazione e gestione di finestre in Xcode

Quando si crea una nuova applicazione Xamarin.Mac Cocoa, si ottiene una finestra vuota standard per impostazione predefinita. Questa finestra viene definita in un .storyboard file incluso automaticamente nel progetto. Per modificare la progettazione delle finestre, nella Esplora soluzioni fare doppio clic sul Main.storyboard file:

Selecting the main storyboard

Verrà aperta la progettazione della finestra in Interface Builder di Xcode:

Editing the UI in Xcode

In Controllo attributi sono disponibili diverse proprietà che è possibile usare per definire e controllare la finestra:

  • Titolo : testo che verrà visualizzato nella barra del titolo della finestra.
  • Salvataggio automatico: si tratta della chiave che verrà usata per ID della finestra quando viene salvata automaticamente la posizione e le impostazioni.
  • Barra del titolo: visualizza una barra del titolo nella finestra.
  • Titolo unificato e barra degli strumenti : se la finestra include una barra degli strumenti, deve far parte della barra del titolo.
  • Visualizzazione contenuto con dimensioni complete: consente all'area del contenuto della finestra di trovarsi sotto la barra del titolo.
  • Ombreggiatura : la finestra ha un'ombreggiatura.
  • Trama: le finestre con trama possono usare effetti (come la vibrazione) e possono essere spostate trascinando in qualsiasi punto del corpo.
  • Chiudi : la finestra ha un pulsante di chiusura.
  • Riduci a icona : la finestra ha un pulsante a icona.
  • Ridimensiona : la finestra ha un controllo di ridimensionamento.
  • Pulsante barra degli strumenti: la finestra dispone di un pulsante nascondi/mostra barra degli strumenti.
  • Ripristinabile : la posizione e le impostazioni della finestra vengono salvate e ripristinate automaticamente.
  • Visibile all'avvio : la finestra viene visualizzata automaticamente quando il .xib file viene caricato.
  • Nascondi su disattiva : la finestra è nascosta quando l'applicazione entra in background.
  • Release When Closed (Rilascio chiuso ) - La finestra viene rimossa dalla memoria quando viene chiusa.
  • Visualizza sempre descrizioni comando : le descrizioni comando vengono visualizzate costantemente.
  • Ricalcola ciclo di visualizzazione: l'ordine di visualizzazione viene ricalcolato prima che venga disegnata la finestra.
  • Spaces, Exposé e Cycling : tutti definiscono il comportamento della finestra in tali ambienti macOS.
  • Schermo intero: determina se questa finestra può accedere alla modalità schermo intero.
  • Animazione : controlla il tipo di animazione disponibile per la finestra.
  • Aspetto : controlla l'aspetto della finestra. Per ora c'è solo un aspetto, Aqua.

Per altri dettagli, vedere la documentazione introduttiva di Apple a Windows e NSWindow .

Impostazione delle dimensioni e della posizione predefinite

Per impostare la posizione iniziale della finestra e controllarne le dimensioni, passare a Controllo dimensioni:

The default size and location

Da qui è possibile impostare le dimensioni iniziali della finestra, assegnargli una dimensione minima e massima, impostare la posizione iniziale sullo schermo e controllare i bordi intorno alla finestra.

Impostazione di un controller finestra principale personalizzato

Per poter creare outlet e azioni per esporre elementi dell'interfaccia utente al codice C#, l'app Xamarin.Mac dovrà usare un controller finestra personalizzato.

Effettua le operazioni seguenti:

  1. Aprire lo storyboard dell'app in Interface Builder di Xcode.

  2. Selezionare nell'area NSWindowController di progettazione.

  3. Passare alla visualizzazione Identity Inspector e immettere WindowController come Nome classe:

    Setting the class name

  4. Salvare le modifiche e tornare a Visual Studio per Mac da sincronizzare.

  5. Un WindowController.cs file verrà aggiunto al progetto nel Esplora soluzioni in Visual Studio per Mac:

    Selecting the windows controller

  6. Riaprire lo storyboard in Interface Builder di Xcode.

  7. Il WindowController.h file sarà disponibile per l'uso:

    Editing the WindowController.h file

Aggiunta di elementi dell'interfaccia utente

Per definire il contenuto di una finestra, trascinare i controlli da Controllo libreria nell'editor dell'interfaccia. Per altre informazioni sull'uso di Interface Builder per creare e abilitare i controlli, vedere la documentazione introduzione a Xcode e Interface Builder .

Ad esempio, trascinare una barra degli strumenti da Controllo libreria nella finestra nell'editor dell'interfaccia:

Selecting a Toolbar from the Library

Trascinare quindi in una visualizzazione testo e ridimensionarlo per riempire l'area sotto la barra degli strumenti:

Adding a Text View

Poiché si vuole che la visualizzazione testo si compatta e cresca man mano che cambiano le dimensioni della finestra, passare all'Editorvincoli e aggiungere i vincoli seguenti:

Editing constraints

Facendo clic sui quattro raggi I-Rosso nella parte superiore dell'editor e facendo clic su Aggiungi 4 vincoli, si sta dicendo alla visualizzazione testo di attenersi alle coordinate X,Y e aumentare o ridurre orizzontalmente e verticalmente mentre la finestra viene ridimensionata.

Infine, esporre la visualizzazione testo al codice usando un outlet (assicurandosi di selezionare il ViewController.h file):

Configuring an outlet

Salvare le modifiche e tornare a Visual Studio per Mac per la sincronizzazione con Xcode.

Per ulteriori informazioni sull'uso di outlet e azioni, vedere la documentazione relativa a Outlet e Action.

Flusso di lavoro della finestra standard

Per qualsiasi finestra creata e operatore nell'applicazione Xamarin.Mac, il processo è fondamentalmente identico a quello appena fatto in precedenza:

  1. Per le nuove finestre che non sono l'impostazione predefinita aggiunta automaticamente al progetto, aggiungere una nuova definizione di finestra al progetto. Questo argomento verrà illustrato in dettaglio di seguito.
  2. Fare doppio clic sul Main.storyboard file per aprire la progettazione della finestra per la modifica in Interface Builder di Xcode.
  3. Trascinare una nuova finestra nella progettazione dell'interfaccia utente e associare la finestra nella finestra principale usando Segues (per altre informazioni, vedere la sezione Segues della documentazione sull'uso degli storyboard ).
  4. Impostare le proprietà della finestra necessarie in Controllo attributi e Controllo dimensioni.
  5. Trascinare i controlli necessari per compilare l'interfaccia e configurarli in Controllo attributi.
  6. Usare Controllo dimensioni per gestire il ridimensionamento per gli elementi dell'interfaccia utente.
  7. Esporre gli elementi dell'interfaccia utente della finestra al codice C# tramite outlet e azioni.
  8. Salvare le modifiche e tornare a Visual Studio per Mac per la sincronizzazione con Xcode.

Ora che è stata creata una finestra di base, si esamineranno i processi tipici che un'applicazione Xamarin.Mac esegue durante l'uso delle finestre.

Visualizzazione della finestra predefinita

Per impostazione predefinita, una nuova applicazione Xamarin.Mac visualizzerà automaticamente la finestra definita nel file all'avvio MainWindow.xib :

An example window running

Dopo aver modificato la progettazione di tale finestra sopra, ora include un controllo Barra degli strumenti e Visualizzazione testo predefinito. La sezione seguente nel file è responsabile della Info.plist visualizzazione di questa finestra:

Editing Info.plist

L'elenco a discesa Interfaccia principale viene usato per selezionare lo storyboard che verrà usato come interfaccia utente principale dell'app (in questo caso Main.storyboard).

Un controller di visualizzazione viene aggiunto automaticamente al progetto per controllare che le finestre principali visualizzate (insieme alla relativa visualizzazione primaria). Viene definito nel ViewController.cs file e allegato al proprietario del file in Interface Builder in Identity Inspector:

Setting the file's owner

Per la finestra, è consigliabile avere un titolo di untitled quando viene aperto per la prima volta, quindi eseguire l'override del ViewWillAppear metodo in ViewController.cs per avere un aspetto simile al seguente:

public override void ViewWillAppear ()
{
    base.ViewWillAppear ();

    // Set Window Title
    this.View.Window.Title = "untitled";
}

Nota

La proprietà della Title finestra viene impostata nel ViewWillAppear metodo anziché nel ViewDidLoad metodo perché, mentre la visualizzazione potrebbe essere caricata in memoria, non è ancora completamente creata un'istanza. L'accesso alla Title proprietà nel ViewDidLoad metodo otterremo un'eccezione null perché la finestra non è stata ancora costruita e cablata fino alla proprietà.

Chiusura a livello di codice di una finestra

In alcuni casi potrebbe essere necessario chiudere una finestra a livello di codice in un'applicazione Xamarin.Mac, diversamente dal fatto che l'utente faccia clic sul pulsante Chiudi della finestra o usi una voce di menu. macOS offre due modi diversi per chiudere un oggetto NSWindow a livello di codice: PerformClose e Close.

PerformClose

La chiamata al PerformClose metodo di un NSWindow oggetto simula l'utente che fa clic sul pulsante Chiudi della finestra evidenziando momentaneamente il pulsante e quindi chiudendo la finestra.

Se l'applicazione implementa l'evento NSWindow, WillClose verrà generato prima della chiusura della finestra. Se l'evento restituisce false, la finestra non verrà chiusa. Se la finestra non dispone di un pulsante Chiudi o non può essere chiusa per qualsiasi motivo, il sistema operativo genererà il suono dell'avviso.

Ad esempio:

MyWindow.PerformClose(this);

Tenta di chiudere l'istanza MyWindowNSWindow . In caso di esito positivo, la finestra verrà chiusa, altrimenti il suono dell'avviso verrà generato e rimarrà aperto.

Chiusura

La chiamata al Close metodo di un NSWindow oggetto non simula l'utente che fa clic sul pulsante Chiudi della finestra evidenziando momentaneamente il pulsante, chiude semplicemente la finestra.

Una finestra non deve essere visibile per essere chiusa e verrà inviata una NSWindowWillCloseNotification notifica al Centro notifiche predefinito per la chiusura della finestra.

Il Close metodo differisce in due modi importanti dal PerformClose metodo :

  1. Non tenta di generare l'evento WillClose .
  2. Non simula l'utente che fa clic sul pulsante Chiudi evidenziando momentaneamente il pulsante.

Ad esempio:

MyWindow.Close();

Chiudere l'istanza MyWindowNSWindow .

Contenuto delle finestre modificate

In macOS, Apple ha fornito un modo per informare l'utente che il contenuto di una finestra (NSWindow) è stato modificato dall'utente e deve essere salvato. Se la finestra contiene contenuto modificato, verrà visualizzato un piccolo punto nero nel widget Chiudi :

A window with the modified marker

Se l'utente tenta di chiudere la finestra o di chiudere l'app Mac mentre sono state apportate modifiche non salvate al contenuto della finestra, è necessario presentare una finestra di dialogo o un foglio modale e consentire all'utente di salvare prima le modifiche:

A save sheet being shown when the window is closed

Contrassegno di una finestra come modificata

Per contrassegnare una finestra come contenuto modificato, usare il codice seguente:

// Mark Window content as modified
Window.DocumentEdited = true;

Dopo aver salvato la modifica, deselezionare il flag modificato usando:

// Mark Window content as not modified
Window.DocumentEdited = false;

Salvataggio delle modifiche prima della chiusura di una finestra

Per controllare se l'utente chiude una finestra e consentire loro di salvare il contenuto modificato in anticipo, è necessario creare una sottoclasse di NSWindowDelegate ed eseguire l'override del relativo WindowShouldClose metodo. Ad esempio:

using System;
using AppKit;
using System.IO;
using Foundation;

namespace SourceWriter
{
    public class EditorWindowDelegate : NSWindowDelegate
    {
        #region Computed Properties
        public NSWindow Window { get; set;}
        #endregion

        #region constructors
        public EditorWindowDelegate (NSWindow window)
        {
            // Initialize
            this.Window = window;

        }
        #endregion

        #region Override Methods
        public override bool WindowShouldClose (Foundation.NSObject sender)
        {
            // is the window dirty?
            if (Window.DocumentEdited) {
                var alert = new NSAlert () {
                    AlertStyle = NSAlertStyle.Critical,
                    InformativeText = "Save changes to document before closing window?",
                    MessageText = "Save Document",
                };
                alert.AddButton ("Save");
                alert.AddButton ("Lose Changes");
                alert.AddButton ("Cancel");
                var result = alert.RunSheetModal (Window);

                // Take action based on result
                switch (result) {
                case 1000:
                    // Grab controller
                    var viewController = Window.ContentViewController as ViewController;

                    // Already saved?
                    if (Window.RepresentedUrl != null) {
                        var path = Window.RepresentedUrl.Path;

                        // Save changes to file
                        File.WriteAllText (path, viewController.Text);
                        return true;
                    } else {
                        var dlg = new NSSavePanel ();
                        dlg.Title = "Save Document";
                        dlg.BeginSheet (Window, (rslt) => {
                            // File selected?
                            if (rslt == 1) {
                                var path = dlg.Url.Path;
                                File.WriteAllText (path, viewController.Text);
                                Window.DocumentEdited = false;
                                viewController.View.Window.SetTitleWithRepresentedFilename (Path.GetFileName(path));
                                viewController.View.Window.RepresentedUrl = dlg.Url;
                                Window.Close();
                            }
                        });
                        return true;
                    }
                    return false;
                case 1001:
                    // Lose Changes
                    return true;
                case 1002:
                    // Cancel
                    return false;
                }
            }

            return true;
        }
        #endregion
    }
}

Usare il codice seguente per collegare un'istanza di questo delegato alla finestra:

// Set delegate
Window.Delegate = new EditorWindowDelegate(Window);

Salvataggio delle modifiche prima della chiusura dell'app

Infine, l'app Xamarin.Mac deve verificare se una delle sue finestre contiene contenuto modificato e consentire all'utente di salvare le modifiche prima di uscire. A tale scopo, modificare il AppDelegate.cs file, eseguire l'override del ApplicationShouldTerminate metodo e renderlo simile al seguente:

public override NSApplicationTerminateReply ApplicationShouldTerminate (NSApplication sender)
{
    // See if any window needs to be saved first
    foreach (NSWindow window in NSApplication.SharedApplication.Windows) {
        if (window.Delegate != null && !window.Delegate.WindowShouldClose (this)) {
            // Did the window terminate the close?
            return NSApplicationTerminateReply.Cancel;
        }
    }

    // Allow normal termination
    return NSApplicationTerminateReply.Now;
}

Uso di più finestre

La maggior parte delle applicazioni Mac basate su documenti può modificare più documenti contemporaneamente. Ad esempio, un editor di testo può avere più file di testo aperti per la modifica contemporaneamente. Per impostazione predefinita, una nuova applicazione Xamarin.Mac include un menu File con un nuovo elemento cablato automaticamente all'azionenewDocument:.

Il codice seguente attiverà questo nuovo elemento e consentirà all'utente di aprire più copie della finestra principale per modificare più documenti contemporaneamente.

Modificare il AppDelegate.cs file e aggiungere la proprietà calcolata seguente:

public int UntitledWindowCount { get; set;} =1;

Usa questa opzione per tenere traccia del numero di file non salvati in modo da poter inviare commenti e suggerimenti all'utente (in base alle linee guida di Apple, come illustrato in precedenza).

Aggiungere quindi il metodo seguente:

[Export ("newDocument:")]
void NewDocument (NSObject sender) {
    // Get new window
    var storyboard = NSStoryboard.FromName ("Main", null);
    var controller = storyboard.InstantiateControllerWithIdentifier ("MainWindow") as NSWindowController;

    // Display
    controller.ShowWindow(this);

    // Set the title
    controller.Window.Title = (++UntitledWindowCount == 1) ? "untitled" : string.Format ("untitled {0}", UntitledWindowCount);
}

Questo codice crea una nuova versione del controller finestra, carica la nuova finestra, lo imposta come finestra principale e chiave e imposta il titolo. A questo punto, se si esegue l'applicazione e si seleziona Nuovo dal menu File verrà aperta e visualizzata una nuova finestra dell'editor:

A new untitled window was added

Se si apre il menu di Windows , è possibile vedere che l'applicazione esegue automaticamente il rilevamento e la gestione delle finestre aperte:

The windows menu

Per altre informazioni sull'uso dei menu in un'applicazione Xamarin.Mac, vedere la documentazione relativa all'uso dei menu .

Recupero della finestra attualmente attiva

In un'applicazione Xamarin.Mac in grado di aprire più finestre (documenti), in alcuni casi è necessario ottenere la finestra corrente più in alto (la finestra chiave). Il codice seguente restituirà la finestra della chiave:

var window = NSApplication.SharedApplication.KeyWindow;

Può essere chiamato in qualsiasi classe o metodo che deve accedere alla finestra della chiave corrente. Se non è attualmente aperta alcuna finestra, restituirà null.

Accesso a tutte le finestre dell'app

In alcuni casi potrebbe essere necessario accedere a tutte le finestre attualmente aperte dall'app Xamarin.Mac. Ad esempio, per verificare se un file che l'utente vuole aprire è già aperto in una finestra di uscita.

NSApplication.SharedApplication Mantiene una proprietà che contiene una Windows matrice di tutte le finestre aperte nell'app. È possibile scorrere questa matrice per accedere a tutte le finestre correnti dell'app. Ad esempio:

// Is the file already open?
for(int n=0; n<NSApplication.SharedApplication.Windows.Length; ++n) {
    var content = NSApplication.SharedApplication.Windows[n].ContentViewController as ViewController;
    if (content != null && path == content.FilePath) {
        // Bring window to front
        NSApplication.SharedApplication.Windows[n].MakeKeyAndOrderFront(this);
        return true;
    }
}

Nel codice di esempio viene eseguito il cast di ogni finestra restituita alla classe personalizzata ViewController nell'app e il test del valore di una proprietà personalizzata Path sul percorso di un file che l'utente vuole aprire. Se il file è già aperto, la finestra verrà visualizzata in primo piano.

Regolazione delle dimensioni della finestra nel codice

In alcuni casi l'applicazione deve ridimensionare una finestra nel codice. Per ridimensionare e riposizionare una finestra, modificare la Frame proprietà. Quando si regolano le dimensioni di una finestra, in genere è necessario regolare anche l'origine, per mantenere la finestra nella stessa posizione a causa del sistema di coordinate di macOS.

A differenza di iOS in cui l'angolo superiore sinistro rappresenta (0,0), macOS usa un sistema di coordinate matematiche in cui l'angolo inferiore sinistro dello schermo rappresenta (0,0). In iOS le coordinate aumentano man mano che si sposta verso il basso verso destra. In macOS le coordinate aumentano verso l'alto verso l'alto verso destra.

Il codice di esempio seguente ridimensiona una finestra:

nfloat y = 0;

// Calculate new origin
y = Frame.Y - (768 - Frame.Height);

// Resize and position window
CGRect frame = new CGRect (Frame.X, y, 1024, 768);
SetFrame (frame, true);

Importante

Quando si modificano le dimensioni e la posizione delle finestre nel codice, è necessario assicurarsi di rispettare le dimensioni minime e massime impostate in Interface Builder. Questo non verrà rispettato automaticamente e sarete in grado di rendere la finestra più grande o più piccola di questi limiti.

Monitoraggio delle modifiche alle dimensioni della finestra

In alcuni casi potrebbe essere necessario monitorare le modifiche nelle dimensioni di una finestra all'interno dell'app Xamarin.Mac. Ad esempio, per ridisegnare il contenuto in base alle nuove dimensioni.

Per monitorare le modifiche delle dimensioni, assicurarsi prima di tutto di aver assegnato una classe personalizzata per il controller di finestra in Interface Builder di Xcode. Ad esempio, MasterWindowController nell'esempio seguente:

The Identity Inspector

Modificare quindi la classe window controller personalizzata e monitorare l'evento DidResize nella finestra del controller per ricevere una notifica delle modifiche delle dimensioni in tempo reale. Ad esempio:

public override void WindowDidLoad ()
{
    base.WindowDidLoad ();

    Window.DidResize += (sender, e) => {
        // Do something as the window is being live resized
    };
}

Facoltativamente, puoi usare l'evento DidEndLiveResize per ricevere una notifica solo dopo che l'utente ha terminato di modificare le dimensioni della finestra. Ad esempio:

public override void WindowDidLoad ()
{
    base.WindowDidLoad ();

        Window.DidEndLiveResize += (sender, e) => {
        // Do something after the user's finished resizing
        // the window
    };
}

Impostazione del titolo e del file rappresentato di una finestra

Quando si utilizzano finestre che rappresentano i documenti, NSWindow dispone di una DocumentEdited proprietà che, se impostata su true visualizza un piccolo punto nel pulsante Chiudi per fornire all'utente un'indicazione che il file è stato modificato e deve essere salvato prima della chiusura.

Modificare il ViewController.cs file e apportare le modifiche seguenti:

public bool DocumentEdited {
    get { return View.Window.DocumentEdited; }
    set { View.Window.DocumentEdited = value; }
}
...

public override void ViewWillAppear ()
{
    base.ViewWillAppear ();

    // Set Window Title
    this.View.Window.Title = "untitled";

    View.Window.WillClose += (sender, e) => {
        // is the window dirty?
        if (DocumentEdited) {
            var alert = new NSAlert () {
                AlertStyle = NSAlertStyle.Critical,
                InformativeText = "We need to give the user the ability to save the document here...",
                MessageText = "Save Document",
            };
            alert.RunModal ();
        }
    };
}

public override void AwakeFromNib ()
{
    base.AwakeFromNib ();

    // Show when the document is edited
    DocumentEditor.TextDidChange += (sender, e) => {
        // Mark the document as dirty
        DocumentEdited = true;
    };

    // Overriding this delegate is required to monitor the TextDidChange event
    DocumentEditor.ShouldChangeTextInRanges += (NSTextView view, NSValue[] values, string[] replacements) => {
        return true;
    };

}

È inoltre in corso il monitoraggio dell'evento WillClose nella finestra e il controllo dello stato della DocumentEdited proprietà. Se è true necessario concedere all'utente la possibilità di salvare le modifiche apportate al file. Se si esegue l'app e si immette un testo, verrà visualizzato il punto:

A changed window

Se si tenta di chiudere la finestra, viene visualizzato un avviso:

Displaying a save dialog

Se si carica un documento da un file, impostare il titolo della finestra sul nome del file usando il window.SetTitleWithRepresentedFilename (Path.GetFileName(path)); metodo , dato che è una stringa che path rappresenta il file aperto. Inoltre, è possibile impostare l'URL del file usando il window.RepresentedUrl = url; metodo .

Se l'URL punta a un tipo di file noto dal sistema operativo, la relativa icona verrà visualizzata nella barra del titolo. Se l'utente fa clic con il pulsante destro del mouse sull'icona, verrà visualizzato il percorso del file.

Modificare il AppDelegate.cs file e aggiungere il metodo seguente:

[Export ("openDocument:")]
void OpenDialog (NSObject sender)
{
    var dlg = NSOpenPanel.OpenPanel;
    dlg.CanChooseFiles = true;
    dlg.CanChooseDirectories = false;

    if (dlg.RunModal () == 1) {
        // Nab the first file
        var url = dlg.Urls [0];

        if (url != null) {
            var path = url.Path;

            // Get new window
            var storyboard = NSStoryboard.FromName ("Main", null);
            var controller = storyboard.InstantiateControllerWithIdentifier ("MainWindow") as NSWindowController;

            // Display
            controller.ShowWindow(this);

            // Load the text into the window
            var viewController = controller.Window.ContentViewController as ViewController;
            viewController.Text = File.ReadAllText(path);
                    viewController.View.Window.SetTitleWithRepresentedFilename (Path.GetFileName(path));
            viewController.View.Window.RepresentedUrl = url;

        }
    }
}

Ora, se si esegue l'app, selezionare Apri dal menu File, selezionare un file di testo dalla finestra di dialogo Apri e aprirlo:

An open dialog box

Il file verrà visualizzato e il titolo verrà impostato con l'icona del file:

The contents of a file loaded

Aggiunta di una nuova finestra a un progetto

A parte la finestra del documento principale, potrebbe essere necessario che un'applicazione Xamarin.Mac visualizzi altri tipi di finestre all'utente, ad esempio Preferenze o Pannelli di controllo.

Per aggiungere una nuova finestra, eseguire le operazioni seguenti:

  1. Nella Esplora soluzioni fare doppio clic sul Main.storyboard file per aprirlo per la modifica in Interface Builder di Xcode.

  2. Trascinare un nuovo controller finestra dalla libreria e rilasciarlo nell'area di progettazione:

    Selecting a new Window Controller in the Library

  3. In Identity Inspector (Controllo identità) immettere PreferencesWindow per l'ID storyboard:

    Setting the storyboard ID

  4. Progettare l'interfaccia:

    Designing the UI

  5. Aprire il menu dell'app (MacWindows), selezionare Preferenze, Fare clic e trascinare nella nuova finestra:

    Creating a segue

  6. Selezionare Mostra dal menu popup.

  7. Salvare le modifiche e tornare a Visual Studio per Mac per la sincronizzazione con Xcode.

Se si esegue il codice e si seleziona Preferenze dalmenu Applicazione, verrà visualizzata la finestra:

A sample preferences menu

Uso dei pannelli

Come indicato all'inizio di questo articolo, un pannello galleggia sopra altre finestre e fornisce strumenti o controlli che gli utenti possono usare mentre i documenti sono aperti.

Proprio come qualsiasi altro tipo di finestra creato e usato nell'applicazione Xamarin.Mac, il processo è fondamentalmente lo stesso:

  1. Aggiungere una nuova definizione di finestra al progetto.
  2. Fare doppio clic sul .xib file per aprire la progettazione della finestra per la modifica in Interface Builder di Xcode.
  3. Impostare le proprietà della finestra necessarie in Controllo attributi e Controllo dimensioni.
  4. Trascinare i controlli necessari per compilare l'interfaccia e configurarli in Controllo attributi.
  5. Usare Controllo dimensioni per gestire il ridimensionamento per gli elementi dell'interfaccia utente.
  6. Esporre gli elementi dell'interfaccia utente della finestra al codice C# tramite outlet e azioni.
  7. Salvare le modifiche e tornare a Visual Studio per Mac per la sincronizzazione con Xcode.

In Controllo attributi sono disponibili le opzioni seguenti specifiche per Pannelli:

The Attribute Inspector

  • Stile - Consente di regolare lo stile del pannello da: Pannello normale (simile a una finestra standard), Pannello utilità (con una barra del titolo più piccola), pannello HUD (è traslucente e la barra del titolo fa parte dello sfondo).
  • Non Attivazione : determina nel pannello diventa la finestra chiave.
  • Modale documento: se modale documento, il pannello verrà spostato solo sopra le finestre dell'applicazione, altrimenti viene spostato sopra tutto.

Per aggiungere un nuovo pannello, eseguire le operazioni seguenti:

  1. Nel Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto e scegliere Aggiungi>nuovo file...

  2. Nella finestra di dialogo Nuovo file selezionare Xamarin.Mac Cocoa Window with Controller (Finestra cocoa Xamarin.Mac>con controller):

    Adding a new window controller

  3. Immettere DocumentPanel in Nome e fare clic sul pulsante Nuovo.

  4. Fare doppio clic sul DocumentPanel.xib file per aprirlo per la modifica in Interface Builder:

    Editing the panel

  5. Eliminare la finestra esistente e trascinare un pannello dal controllo libreria nell'editor dell'interfaccia:

    Deleting the existing window

  6. Collegare il pannello all'uscita della finestra - Proprietario - del file:

    Dragging to wire up the panel

  7. Passare a Identity Inspector e impostare la classe panel su DocumentPanel:

    Setting the panel's class

  8. Salvare le modifiche e tornare a Visual Studio per Mac per la sincronizzazione con Xcode.

  9. Modificare il DocumentPanel.cs file e modificare la definizione della classe nel modo seguente:

    public partial class DocumentPanel : NSPanel

  10. Salvare le modifiche apportate al file.

Modificare il AppDelegate.cs file e fare in modo che il DidFinishLaunching metodo sia simile al seguente:

public override void DidFinishLaunching (NSNotification notification)
{
        // Display panel
    var panel = new DocumentPanelController ();
    panel.Window.MakeKeyAndOrderFront (this);
}

Se si esegue l'applicazione, verrà visualizzato il pannello:

The panel in a running app

Importante

Le finestre del pannello sono state deprecate da Apple e devono essere sostituite con le interfacce inspector. Per un esempio completo della creazione di un controllo in un'app Xamarin.Mac, vedere l'app di esempio MacInspector .

Riepilogo

Questo articolo ha esaminato in dettaglio l'uso di Windows e Pannelli in un'applicazione Xamarin.Mac. Sono stati illustrati i diversi tipi e usi di Windows e Pannelli, come creare e gestire Windows e Pannelli in Interface Builder di Xcode e come usare Windows e Pannelli nel codice C#.