Partager via


Conception de l’interface utilisateur .storyboard/.xib-less dans Xamarin.Mac

Cet article traite de la création d’une interface utilisateur de l’application Xamarin.Mac directement à partir du code C#, sans fichiers .storyboard, fichiers .xib ou Générateur d’interface.

Vue d’ensemble

Lorsque vous utilisez C# et .NET dans une application Xamarin.Mac, vous avez accès aux mêmes éléments et outils d’interface utilisateur qu’un développeur travaillant dans Objective-C et Xcode . En règle générale, lors de la création d’une application Xamarin.Mac, vous allez utiliser le Générateur d’interface de Xcode avec des fichiers .storyboard ou .xib pour créer et gérer l’interface utilisateur de votre application.

Vous avez également la possibilité de créer une partie ou l’ensemble de l’interface utilisateur de votre application Xamarin.Mac directement dans le code C#. Dans cet article, nous allons aborder les principes fondamentaux de la création d’interfaces utilisateur et d’éléments d’interface utilisateur dans le code C#.

Éditeur de code Visual Studio pour Mac

Changement d’une fenêtre pour utiliser du code

Lorsque vous créez une application Xamarin.Mac Cocoa, vous obtenez une fenêtre vide standard par défaut. Cette fenêtre est définie dans un fichier Main.storyboard (ou traditionnellement un fichier MainWindow.xib) automatiquement inclus dans le projet. Cela inclut également un fichier ViewController.cs qui gère la vue principale de l’application (ou encore une fois un MainWindow.cs et un fichier MainWindowController.cs ).

Pour basculer vers une fenêtre Xibless pour une application, procédez comme suit :

  1. Ouvrez l’application que vous souhaitez arrêter d’utiliser .storyboard ou de fichiers .xib pour définir l’interface utilisateur dans Visual Studio pour Mac.

  2. Dans le panneau Solution, cliquez avec le bouton droit sur le fichier Main.storyboard ou MainWindow.xib , puis sélectionnez Supprimer :

    Suppression du storyboard ou de la fenêtre principale

  3. Dans la boîte de dialogue Supprimer, cliquez sur le bouton Supprimer pour supprimer complètement le .storyboard ou .xib du projet :

    Confirmation de la suppression

Nous devons maintenant modifier le fichier MainWindow.cs pour définir la disposition de la fenêtre et modifier le fichier ViewController.cs ou MainWindowController.cs pour créer une instance de notre MainWindow classe, car nous n’utilisons plus le fichier .storyboard ou .xib.

Les applications Xamarin.Mac modernes qui utilisent des storyboards pour leur interface utilisateur peuvent ne pas inclure automatiquement les fichiers MainWindow.cs, ViewController.cs ou MainWindowController.cs . Comme nécessaire, ajoutez simplement une nouvelle classe C# vide au projet (Ajouter>un nouveau fichier...>Classe General>Empty) et nommez-la de la même façon que le fichier manquant.

Définition de la fenêtre dans le code

Ensuite, modifiez le fichier MainWindow.cs et faites-le ressembler à ce qui suit :

using System;
using Foundation;
using AppKit;
using CoreGraphics;

namespace MacXibless
{
    public partial class MainWindow : NSWindow
    {
        #region Private Variables
        private int NumberOfTimesClicked = 0;
        #endregion

        #region Computed Properties
        public NSButton ClickMeButton { get; set;}
        public NSTextField ClickMeLabel { get ; set;}
        #endregion

        #region Constructors
        public MainWindow (IntPtr handle) : base (handle)
        {
        }

        [Export ("initWithCoder:")]
        public MainWindow (NSCoder coder) : base (coder)
        {
        }

        public MainWindow(CGRect contentRect, NSWindowStyle aStyle, NSBackingStore bufferingType, bool deferCreation): base (contentRect, aStyle,bufferingType,deferCreation) {
            // Define the user interface of the window here
            Title = "Window From Code";

            // Create the content view for the window and make it fill the window
            ContentView = new NSView (Frame);

            // Add UI elements to window
            ClickMeButton = new NSButton (new CGRect (10, Frame.Height-70, 100, 30)){
                AutoresizingMask = NSViewResizingMask.MinYMargin
            };
            ContentView.AddSubview (ClickMeButton);

            ClickMeLabel = new NSTextField (new CGRect (120, Frame.Height - 65, Frame.Width - 130, 20)) {
                BackgroundColor = NSColor.Clear,
                TextColor = NSColor.Black,
                Editable = false,
                Bezeled = false,
                AutoresizingMask = NSViewResizingMask.WidthSizable | NSViewResizingMask.MinYMargin,
                StringValue = "Button has not been clicked yet."
            };
            ContentView.AddSubview (ClickMeLabel);
        }
        #endregion

        #region Override Methods
        public override void AwakeFromNib ()
        {
            base.AwakeFromNib ();

            // Wireup events
            ClickMeButton.Activated += (sender, e) => {
                // Update count
                ClickMeLabel.StringValue = (++NumberOfTimesClicked == 1) ? "Button clicked one time." : string.Format("Button clicked {0} times.",NumberOfTimesClicked);
            };
        }
        #endregion

    }
}

Examinons quelques-uns des éléments clés.

Tout d’abord, nous avons ajouté quelques propriétés calculées qui agiront comme des points de sortie (comme si la fenêtre a été créée dans un fichier .storyboard ou .xib) :

public NSButton ClickMeButton { get; set;}
public NSTextField ClickMeLabel { get ; set;}

Celles-ci nous donneront accès aux éléments d’interface utilisateur que nous allons afficher sur la fenêtre. Étant donné que la fenêtre n’est pas gonflée à partir d’un fichier .storyboard ou .xib, nous avons besoin d’un moyen de l’instancier (comme nous le verrons plus loin dans la MainWindowController classe). C’est ce que fait cette nouvelle méthode de constructeur :

public MainWindow(CGRect contentRect, NSWindowStyle aStyle, NSBackingStore bufferingType, bool deferCreation): base (contentRect, aStyle,bufferingType,deferCreation) {
    ...
}

C’est là que nous allons concevoir la disposition de la fenêtre et placer tous les éléments d’interface utilisateur nécessaires pour créer l’interface utilisateur requise. Avant de pouvoir ajouter des éléments d’interface utilisateur à une fenêtre, il a besoin d’un affichage de contenu pour contenir les éléments :

ContentView = new NSView (Frame);

Cela crée une vue de contenu qui remplira la fenêtre. Maintenant, nous ajoutons notre premier élément d’interface utilisateur, un NSButton, à la fenêtre :

ClickMeButton = new NSButton (new CGRect (10, Frame.Height-70, 100, 30)){
    AutoresizingMask = NSViewResizingMask.MinYMargin
};
ContentView.AddSubview (ClickMeButton);

La première chose à noter ici est que, contrairement à iOS, macOS utilise la notation mathématique pour définir son système de coordonnées de fenêtre. Ainsi, le point d’origine se trouve dans le coin inférieur gauche de la fenêtre, avec des valeurs augmentant vers la droite et vers le coin supérieur droit de la fenêtre. Lorsque nous créons le nouveau NSButton, nous prenons cela en compte, car nous définissons sa position et sa taille sur l’écran.

La AutoresizingMask = NSViewResizingMask.MinYMargin propriété indique au bouton que nous voulons qu’il reste dans le même emplacement en haut de la fenêtre lorsque la fenêtre est redimensionnée verticalement. Là encore, cela est nécessaire, car (0,0) se trouve en bas à gauche de la fenêtre.

Enfin, la ContentView.AddSubview (ClickMeButton) méthode ajoute la NSButton vue de contenu afin qu’elle s’affiche à l’écran lorsque l’application est exécutée et que la fenêtre s’affiche.

Ensuite, une étiquette est ajoutée à la fenêtre qui affiche le nombre de fois où le NSButton clic a été effectué :

ClickMeLabel = new NSTextField (new CGRect (120, Frame.Height - 65, Frame.Width - 130, 20)) {
    BackgroundColor = NSColor.Clear,
    TextColor = NSColor.Black,
    Editable = false,
    Bezeled = false,
    AutoresizingMask = NSViewResizingMask.WidthSizable | NSViewResizingMask.MinYMargin,
    StringValue = "Button has not been clicked yet."
};
ContentView.AddSubview (ClickMeLabel);

Étant donné que macOS n’a pas d’élément d’interface utilisateur Label spécifique, nous avons ajouté un élément d’interface utilisateur de style spécial, non modifiable NSTextField pour agir en tant qu’étiquette. Tout comme le bouton précédent, la taille et l’emplacement prennent en compte que (0,0) se trouve en bas à gauche de la fenêtre. La AutoresizingMask = NSViewResizingMask.WidthSizable | NSViewResizingMask.MinYMargin propriété utilise le ou l’opérateur pour combiner deux NSViewResizingMask fonctionnalités. Cela fait en sorte que l’étiquette reste dans le même emplacement à partir du haut de la fenêtre lorsque la fenêtre est redimensionnée verticalement et réduit et augmente en largeur lorsque la fenêtre est redimensionnée horizontalement.

Là encore, la ContentView.AddSubview (ClickMeLabel) méthode ajoute la NSTextField vue de contenu afin qu’elle s’affiche à l’écran lorsque l’application est exécutée et que la fenêtre s’ouvre.

Ajustement du contrôleur de fenêtre

Étant donné que la conception du MainWindow fichier n’est plus chargée à partir d’un fichier .storyboard ou .xib, nous devons apporter des ajustements au contrôleur de fenêtre. Modifiez le fichier MainWindowController.cs et faites-le ressembler à ce qui suit :

using System;

using Foundation;
using AppKit;
using CoreGraphics;

namespace MacXibless
{
    public partial class MainWindowController : NSWindowController
    {
        public MainWindowController (IntPtr handle) : base (handle)
        {
        }

        [Export ("initWithCoder:")]
        public MainWindowController (NSCoder coder) : base (coder)
        {
        }

        public MainWindowController () : base ("MainWindow")
        {
            // Construct the window from code here
            CGRect contentRect = new CGRect (0, 0, 1000, 500);
            base.Window = new MainWindow(contentRect, (NSWindowStyle.Titled | NSWindowStyle.Closable | NSWindowStyle.Miniaturizable | NSWindowStyle.Resizable), NSBackingStore.Buffered, false);

            // Simulate Awaking from Nib
            Window.AwakeFromNib ();
        }

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

        public new MainWindow Window {
            get { return (MainWindow)base.Window; }
        }
    }
}

Examinons les éléments clés de cette modification.

Tout d’abord, nous définissons une nouvelle instance de la MainWindow classe et l’affectons à la propriété du contrôleur de fenêtre de Window base :

CGRect contentRect = new CGRect (0, 0, 1000, 500);
base.Window = new MainWindow(contentRect, (NSWindowStyle.Titled | NSWindowStyle.Closable | NSWindowStyle.Miniaturizable | NSWindowStyle.Resizable), NSBackingStore.Buffered, false);

Nous définissons l’emplacement de la fenêtre de l’écran avec un CGRect. Tout comme le système de coordonnées de la fenêtre, l’écran définit (0,0) comme coin inférieur gauche. Ensuite, nous définissons le style de la fenêtre à l’aide de l’opérateur Or pour combiner deux fonctionnalités ou plus NSWindowStyle :

... (NSWindowStyle.Titled | NSWindowStyle.Closable | NSWindowStyle.Miniaturizable | NSWindowStyle.Resizable) ...

Les fonctionnalités suivantes NSWindowStyle sont disponibles :

  • Sans bordure : la fenêtre n’aura pas de bordure.
  • Intitulé : la fenêtre aura une barre de titre.
  • Closable : la fenêtre a un bouton Fermer et peut être fermée.
  • Miniaturizable - La fenêtre a un bouton Miniaturize et peut être réduite.
  • Redimensionnable : la fenêtre aura un bouton Redimensionner et sera redimensionnable.
  • Utilitaire : la fenêtre est une fenêtre de style utilitaire (panneau).
  • DocModal : si la fenêtre est un panneau, il s’agit de Document Modal au lieu de System Modal.
  • NonactivatingPanel : si la fenêtre est un panneau, elle n’est pas rendue dans la fenêtre principale.
  • TexturedBackground : la fenêtre aura un arrière-plan texturé.
  • Non mis à l’échelle : la fenêtre ne sera pas mise à l’échelle.
  • UnifiedTitleAndToolbar : les zones de titre et de barre d’outils de la fenêtre seront jointes.
  • Hud - La fenêtre s’affiche sous la forme d’un panneau d’affichage en haut.
  • FullScreenWindow : la fenêtre peut entrer en mode plein écran.
  • FullSizeContentView : la vue de contenu de la fenêtre se trouve derrière la zone de titre et de barre d’outils.

Les deux dernières propriétés définissent le type de mise en mémoire tampon pour la fenêtre et si le dessin de la fenêtre sera différé. Pour plus d’informations sur NSWindows, consultez la documentation d’Apple sur l’introduction à Windows .

Enfin, étant donné que la fenêtre n’est pas gonflée à partir d’un fichier .storyboard ou .xib, nous devons la simuler dans notre MainWindowController.cs en appelant la méthode Windows AwakeFromNib :

Window.AwakeFromNib ();

Cela vous permet de coder sur la fenêtre comme une fenêtre standard chargée à partir d’un fichier .storyboard ou .xib.

Affichage de la fenêtre

Avec le fichier .storyboard ou .xib supprimé et les fichiers MainWindow.cs et MainWindowController.cs modifiés, vous utiliserez la fenêtre comme vous le feriez pour n’importe quelle fenêtre normale créée dans le Générateur d’interface de Xcode avec un fichier .xib.

Les éléments suivants créent une instance de la fenêtre et de son contrôleur et affichent la fenêtre à l’écran :

private MainWindowController mainWindowController;
...

mainWindowController = new MainWindowController ();
mainWindowController.Window.MakeKeyAndOrderFront (this);

À ce stade, si l’application est exécutée et que le bouton a cliqué deux fois, les éléments suivants s’affichent :

Exemple d’exécution d’application

Ajout d’une fenêtre de code uniquement

Si nous voulons ajouter un code uniquement, fenêtre xibless à une application Xamarin.Mac existante, cliquez avec le bouton droit sur le projet dans le panneau Solution et sélectionnez Ajouter>un nouveau fichier... Dans la boîte de dialogue Nouveau fichier, choisissez la fenêtre Cacao Xamarin.Mac>avec le contrôleur, comme illustré ci-dessous :

Ajout d’un nouveau contrôleur de fenêtre

Comme précédemment, nous allons supprimer le fichier .storyboard ou .xib par défaut du projet (dans ce cas SecondWindow.xib) et suivre les étapes décrites dans la section Changer de fenêtre pour utiliser la section Code ci-dessus pour couvrir la définition de la fenêtre en code.

Ajout d’un élément d’interface utilisateur à une fenêtre dans le code

Si une fenêtre a été créée dans du code ou chargée à partir d’un fichier .storyboard ou .xib, il peut arriver que nous souhaitions ajouter un élément d’interface utilisateur à une fenêtre à partir du code. Par exemple :

var ClickMeButton = new NSButton (new CGRect (10, 10, 100, 30)){
    AutoresizingMask = NSViewResizingMask.MinYMargin
};
MyWindow.ContentView.AddSubview (ClickMeButton);

Le code ci-dessus crée un nouveau NSButton code et l’ajoute à l’instance MyWindow de fenêtre à afficher. En fait, n’importe quel élément d’interface utilisateur qui peut être défini dans le Générateur d’interface de Xcode dans un fichier .storyboard ou .xib peut être créé dans le code et affiché dans une fenêtre.

Définition de la barre de menus dans le code

En raison des limitations actuelles dans Xamarin.Mac, il n’est pas recommandé de créer la barre de menus de votre application Xamarin.Mac,NSMenuBar dans le code, mais de continuer à utiliser le fichier Main.storyboard ou MainMenu.xib pour le définir. Cela dit, vous pouvez ajouter et supprimer des menus et des éléments de menu dans le code C#.

Par exemple, modifiez le fichier AppDelegate.cs et faites en sorte que la DidFinishLaunching méthode ressemble à ce qui suit :

public override void DidFinishLaunching (NSNotification notification)
{
    mainWindowController = new MainWindowController ();
    mainWindowController.Window.MakeKeyAndOrderFront (this);

    // Create a Status Bar Menu
    NSStatusBar statusBar = NSStatusBar.SystemStatusBar;

    var item = statusBar.CreateStatusItem (NSStatusItemLength.Variable);
    item.Title = "Phrases";
    item.HighlightMode = true;
    item.Menu = new NSMenu ("Phrases");

    var address = new NSMenuItem ("Address");
    address.Activated += (sender, e) => {
        Console.WriteLine("Address Selected");
    };
    item.Menu.AddItem (address);

    var date = new NSMenuItem ("Date");
    date.Activated += (sender, e) => {
        Console.WriteLine("Date Selected");
    };
    item.Menu.AddItem (date);

    var greeting = new NSMenuItem ("Greeting");
    greeting.Activated += (sender, e) => {
        Console.WriteLine("Greetings Selected");
    };
    item.Menu.AddItem (greeting);

    var signature = new NSMenuItem ("Signature");
    signature.Activated += (sender, e) => {
        Console.WriteLine("Signature Selected");
    };
    item.Menu.AddItem (signature);
}

Le menu ci-dessus crée une barre d’état à partir du code et l’affiche lorsque l’application est lancée. Pour plus d’informations sur l’utilisation des menus, consultez notre documentation sur les menus .

Résumé

Cet article a examiné en détail la création d’une interface utilisateur de l’application Xamarin.Mac en code C# par opposition à l’utilisation du Générateur d’interface de Xcode avec des fichiers .storyboard ou .xib.