.storyboard/.xib-less user interface design in Xamarin.Mac
In diesem Artikel wird die Benutzeroberfläche einer Xamarin.Mac-Anwendung direkt aus C#-Code erstellt, ohne Storyboarddateien, XIB-Dateien oder Interface Builder.
Überblick
Wenn Sie mit C# und .NET in einer Xamarin.Mac-Anwendung arbeiten, haben Sie Zugriff auf dieselben Benutzeroberflächenelemente und Tools, die ein Entwickler ausführt Objective-C und Xcode ausführt. In der Regel verwenden Sie beim Erstellen einer Xamarin.Mac-Anwendung Xcodes Interface Builder mit STORYboard- oder XIB-Dateien, um die Benutzeroberfläche der Anwendung zu erstellen und zu verwalten.
Außerdem haben Sie die Möglichkeit, einige oder alle Benutzeroberflächen Ihrer Xamarin.Mac-Anwendung direkt im C#-Code zu erstellen. In diesem Artikel werden die Grundlagen zum Erstellen von Benutzeroberflächen und UI-Elementen im C#-Code behandelt.
Wechseln eines Fensters zur Verwendung von Code
Wenn Sie eine neue Xamarin.Mac Cocoa-Anwendung erstellen, erhalten Sie standardmäßig ein standardmäßig leeres Fenster. Diese Fenster werden in einer Main.storyboard-Datei (oder traditionell einer MainWindow.xib)-Datei definiert, die automatisch im Projekt enthalten ist. Dies umfasst auch eine ViewController.cs-Datei , die die Hauptansicht der App verwaltet (oder erneut eine MainWindow.cs und eine MainWindowController.cs-Datei ).
Gehen Sie wie folgt vor, um zu einem Xibless-Fenster für eine Anwendung zu wechseln:
Öffnen Sie die Anwendung, die Sie mit der Verwendung
.storyboard
oder XIB-Dateien beenden möchten, um die Benutzeroberfläche in Visual Studio für Mac zu definieren.Klicken Sie im Lösungspad mit der rechten Maustaste auf die Datei "Main.storyboard " oder " MainWindow.xib ", und wählen Sie "Entfernen" aus:
Klicken Sie im Dialogfeld "Entfernen" auf die Schaltfläche "Löschen ", um das Storyboard oder XIB vollständig aus dem Projekt zu entfernen:
Jetzt müssen wir die Datei "MainWindow.cs " ändern, um das Layout des Fensters zu definieren und die Datei "ViewController.cs " oder "MainWindowController.cs " zu ändern, um eine Instanz unserer MainWindow
Klasse zu erstellen, da wir die STORYBOARD- oder XIB-Datei nicht mehr verwenden.
Moderne Xamarin.Mac-Apps, die Storyboards für ihre Benutzeroberfläche verwenden, enthalten möglicherweise nicht automatisch die Dateien "MainWindow.cs", "ViewController.cs " oder "MainWindowController.cs" . Fügen Sie einfach dem Projekt eine neue leere C#-Klasse hinzu (AddNew>File...>Allgemeine>Leere Klasse) und benennen Sie sie mit der fehlenden Datei.
Definieren des Fensters im Code
Bearbeiten Sie als Nächstes die Datei "MainWindow.cs ", und sehen Sie wie folgt aus:
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
}
}
Lassen Sie uns einige der wichtigsten Elemente diskutieren.
Zunächst haben wir einige berechnete Eigenschaften hinzugefügt, die wie Ausgänge fungieren (als ob das Fenster in einer Storyboard- oder XIB-Datei erstellt wurde):
public NSButton ClickMeButton { get; set;}
public NSTextField ClickMeLabel { get ; set;}
Dadurch erhalten wir Zugriff auf die UI-Elemente, die im Fenster angezeigt werden. Da das Fenster nicht aus einer Storyboard- oder XIB-Datei aufgeblasen wird, benötigen wir eine Möglichkeit, es instanziieren zu können (wie wir später in der MainWindowController
Klasse sehen). Das macht diese neue Konstruktormethode:
public MainWindow(CGRect contentRect, NSWindowStyle aStyle, NSBackingStore bufferingType, bool deferCreation): base (contentRect, aStyle,bufferingType,deferCreation) {
...
}
Hier entwerfen wir das Layout des Fensters und platzieren alle UI-Elemente, die zum Erstellen der erforderlichen Benutzeroberfläche erforderlich sind. Bevor wir einem Fenster beliebige UI-Elemente hinzufügen können, benötigt es eine Inhaltsansicht , um die Elemente zu enthalten:
ContentView = new NSView (Frame);
Dadurch wird eine Inhaltsansicht erstellt, die das Fenster ausfüllt. Jetzt fügen wir dem Fenster unser erstes UI-Element, ein , hinzu NSButton
:
ClickMeButton = new NSButton (new CGRect (10, Frame.Height-70, 100, 30)){
AutoresizingMask = NSViewResizingMask.MinYMargin
};
ContentView.AddSubview (ClickMeButton);
Im Gegensatz zu iOS verwendet macOS mathematische Notation zum Definieren des Fensterkoordinatensystems. Der Ursprungspunkt befindet sich also in der unteren linken Ecke des Fensters, wobei die Werte rechts und zur oberen rechten Ecke des Fensters steigen. Wenn wir das neue NSButton
erstellen, berücksichtigen wir dies, während wir seine Position und Größe auf dem Bildschirm definieren.
Die AutoresizingMask = NSViewResizingMask.MinYMargin
Eigenschaft teilt der Schaltfläche mit, dass sie an derselben Position am oberen Rand des Fensters verbleiben soll, wenn die Größe des Fensters vertikal geändert wird. Dies ist erneut erforderlich, da sich (0,0) unten links im Fenster befindet.
Schließlich fügt die ContentView.AddSubview (ClickMeButton)
Methode der NSButton
Inhaltsansicht hinzu, damit sie auf dem Bildschirm angezeigt wird, wenn die Anwendung ausgeführt wird und das Fenster angezeigt wird.
Als Nächstes wird dem Fenster eine Bezeichnung hinzugefügt, die die Anzahl der Angeklickten NSButton
anzeigt:
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);
Da macOS kein bestimmtes Label UI-Element aufweist, haben wir ein speziell formatiertes, nicht bearbeitbares NSTextField
Label-Element hinzugefügt. Genau wie die Schaltfläche vor, berücksichtigt die Größe und Position, dass sich (0,0) unten links im Fenster befindet. Die AutoresizingMask = NSViewResizingMask.WidthSizable | NSViewResizingMask.MinYMargin
Eigenschaft verwendet den Oder-Operator , um zwei NSViewResizingMask
Features zu kombinieren. Dadurch bleibt die Beschriftung an derselben Position am oberen Rand des Fensters, wenn die Größe des Fensters vertikal geändert wird, und verkleinert und vergrößert sich die Breite, während das Fenster horizontal angepasst wird.
Erneut fügt die ContentView.AddSubview (ClickMeLabel)
Methode der NSTextField
Inhaltsansicht hinzu, damit sie auf dem Bildschirm angezeigt wird, wenn die Anwendung ausgeführt wird und das Fenster geöffnet wird.
Anpassen des Fenstercontrollers
Da das Design der MainWindow
Datei nicht mehr aus einer Storyboard- oder XIB-Datei geladen wird, müssen wir einige Anpassungen an den Fenstercontroller vornehmen. Bearbeiten Sie die Datei "MainWindowController.cs ", und sehen Sie wie folgt aus:
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; }
}
}
}
Lassen Sie uns die wichtigsten Elemente dieser Änderung besprechen.
Zunächst definieren wir eine neue Instanz der MainWindow
Klasse und weisen sie der Eigenschaft des Basisfenstercontrollers Window
zu:
CGRect contentRect = new CGRect (0, 0, 1000, 500);
base.Window = new MainWindow(contentRect, (NSWindowStyle.Titled | NSWindowStyle.Closable | NSWindowStyle.Miniaturizable | NSWindowStyle.Resizable), NSBackingStore.Buffered, false);
Wir definieren die Position des Bildschirmfensters mit einer CGRect
. Genau wie das Koordinatensystem des Fensters definiert der Bildschirm (0,0) als die untere linke Ecke. Als Nächstes definieren wir die Formatvorlage des Fensters mithilfe des Or-Operators , um zwei oder mehr NSWindowStyle
Features zu kombinieren:
... (NSWindowStyle.Titled | NSWindowStyle.Closable | NSWindowStyle.Miniaturizable | NSWindowStyle.Resizable) ...
Die folgenden NSWindowStyle
Features sind verfügbar:
- Rahmenlos – Das Fenster hat keinen Rahmen.
- Titel : Das Fenster verfügt über eine Titelleiste.
- Klonbar - Das Fenster verfügt über eine Schaltfläche "Schließen" und kann geschlossen werden.
- Miniaturisierbar – Das Fenster verfügt über eine Miniaturisierungsschaltfläche und kann minimiert werden.
- Größe ändern : Das Fenster verfügt über eine Schaltfläche zum Ändern der Größe und kann geändert werden.
- Hilfsprogramm – Das Fenster ist ein Hilfsprogrammfenster (Panel).
- DocModal – Wenn es sich bei dem Fenster um ein Panel handelt, handelt es sich um "Dokument modal" anstelle von "System Modal".
- Nicht aktivierenPanel – Wenn es sich bei dem Fenster um ein Panel handelt, wird es nicht zum Hauptfenster gemacht.
- TexturedBackground – Das Fenster verfügt über einen texturierten Hintergrund.
- Nicht skaliert – Das Fenster wird nicht skaliert.
- UnifiedTitleAndToolbar – Der Titel und die Symbolleistenbereiche des Fensters werden verknüpft.
- Hud - Das Fenster wird als Head-up Display Panel angezeigt.
- FullScreenWindow – Das Fenster kann den Vollbildmodus eingeben.
- FullSizeContentView – Die Inhaltsansicht des Fensters befindet sich hinter dem Titel und der Symbolleistenbereich.
Die letzten beiden Eigenschaften definieren den Puffertyp für das Fenster und wenn die Zeichnung des Fensters verzögert wird. Weitere Informationen finden NSWindows
Sie in der Apple-Einführung in Windows Dokumentation.
Da das Fenster nicht aus einer Storyboard- oder XIB-Datei aufgeblasen wird, müssen wir es in unserem MainWindowController.cs simulieren, indem die Windows-Methode AwakeFromNib
aufgerufen wird:
Window.AwakeFromNib ();
Auf diese Weise können Sie wie ein Standardfenster, das aus einer Storyboard- oder XIB-Datei geladen wurde, für das Code für das Fenster verwendet werden.
Anzeigen des Fensters
Wenn die .storyboard- oder XIB-Datei entfernt wurde und die Datei "MainWindow.cs" und "MainWindowController.cs" geändert wurden, verwenden Sie das Fenster genauso wie jedes normale Fenster, das in Xcodes Interface Builder mit einer XIB-Datei erstellt wurde.
Im Folgenden wird eine neue Instanz des Fensters und seines Controllers erstellt und das Fenster auf dem Bildschirm angezeigt:
private MainWindowController mainWindowController;
...
mainWindowController = new MainWindowController ();
mainWindowController.Window.MakeKeyAndOrderFront (this);
Wenn die Anwendung ausgeführt wird und auf die Schaltfläche ein paar Mal geklickt wurde, wird Folgendes angezeigt:
Hinzufügen eines nur Codefensters
Wenn wir einem vorhandenen Xamarin.Mac-Anwendungs einen Code nur hinzufügen möchten, klicken Sie mit der rechten Maustaste auf das Projekt im Lösungspad, und wählen Sie "AddNew>Datei"... Wählen Sie im Dialogfeld "Neue Datei" Xamarin.MacCocoa-Fenster>mit Controller aus, wie unten dargestellt:
Genau wie zuvor löschen wir die Standard-Storyboard- oder XIB-Datei aus dem Projekt (in diesem Fall SecondWindow.xib), und führen Sie die Schritte im Abschnitt "Fenster wechseln" aus, um die Definition des Fensters mit Code zu behandeln.
Hinzufügen eines UI-Elements zu einem Fenster im Code
Ob ein Fenster im Code erstellt oder aus einer Storyboard- oder XIB-Datei geladen wurde, gibt es möglicherweise Zeiten, in denen ein UI-Element zu einem Fenster aus Code hinzugefügt werden soll. Beispiel:
var ClickMeButton = new NSButton (new CGRect (10, 10, 100, 30)){
AutoresizingMask = NSViewResizingMask.MinYMargin
};
MyWindow.ContentView.AddSubview (ClickMeButton);
Der obige Code erstellt eine neue NSButton
Und fügt sie zur Anzeigeinstanz des MyWindow
Fensters hinzu. Grundsätzlich kann jedes UI-Element, das im Interface Builder von Xcode in einer Storyboard- oder XIB-Datei definiert werden kann, im Code erstellt und in einem Fenster angezeigt werden.
Definieren der Menüleiste im Code
Aufgrund der aktuellen Einschränkungen in Xamarin.Mac wird nicht empfohlen, dass Sie die MenüleisteNSMenuBar
ihrer Xamarin.Mac-Anwendung erstellen, aber weiterhin die Datei "Main.storyboard " oder " MainMenu.xib" verwenden, um sie zu definieren. Das heißt, Sie können Menüs und Menüelemente im C#-Code hinzufügen und entfernen.
Bearbeiten Sie beispielsweise die Datei "AppDelegate.cs ", und stellen Sie sicher, dass die DidFinishLaunching
Methode wie folgt aussieht:
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);
}
Im obigen Abschnitt wird ein Statusleistenmenü aus Code erstellt und angezeigt, wenn die Anwendung gestartet wird. Weitere Informationen zum Arbeiten mit Menüs finden Sie in unserer Menüdokumentation .
Zusammenfassung
Dieser Artikel hat einen detaillierten Blick auf das Erstellen der Benutzeroberfläche einer Xamarin.Mac-Anwendung im C#-Code im Gegensatz zur Verwendung des Xcode-Schnittstellen-Generators mit STORYBOARD- oder XIB-Dateien gemacht.