.storyboard/.xib-less Benutzeroberflächendesign in Xamarin.Mac
In diesem Artikel wird die Erstellung der Benutzeroberfläche einer Xamarin.Mac-Anwendung direkt aus C#-Code ohne Storyboarddateien, XIB-Dateien oder Schnittstellen-Generator behandelt.
Übersicht
Beim Arbeiten mit C# und .NET in einer Xamarin.Mac-Anwendung haben Sie Zugriff auf die gleichen Benutzeroberflächenelemente und -tools, die ein Entwickler ausführt Objective-C und Xcode ausführt. Normalerweise verwenden Sie beim Erstellen einer Xamarin.Mac-Anwendung den Schnittstellen-Generator von Xcode mit .storyboard- oder XIB-Dateien, um die Benutzeroberfläche der Anwendung zu erstellen und zu Standard.
Sie haben auch die Möglichkeit, einige oder alle Ui Ihrer Xamarin.Mac-Anwendung direkt im C#-Code zu erstellen. In diesem Artikel werden die Grundlagen des Erstellens 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 Standard Ansicht der App verwaltet (oder wieder traditionell 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 nicht mehr verwenden
.storyboard
möchten, oder XIB-Dateien, um die Benutzeroberfläche in Visual Studio für Mac zu definieren.Klicken Sie auf dem 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 MainWindow.cs Datei ändern, um das Layout des Fensters zu definieren und die ViewController.cs - oder MainWindowController.cs-Datei 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 dem Projekt einfach eine neue leere C#-Klasse hinzu (Neue Datei hinzufügen...>>General>Empty Class) and name it the same as the missing file.
Definieren des Fensters im Code
Bearbeiten Sie als Nächstes die MainWindow.cs Datei, 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 besprechen.
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). Dies geschieht mit dieser neuen 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, muss eine Inhaltsansicht die Elemente enthalten:
ContentView = new NSView (Frame);
Dadurch wird eine Inhaltsansicht erstellt, die das Fenster ausfüllt. Nun fügen wir das erste UI-Element, ein NSButton
, zum Fenster hinzu:
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 in Richtung der 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 vom oberen Rand des Fensters bleibt, wenn die Größe des Fensters vertikal geändert wird. Auch hier ist dies erforderlich, da sich (0,0) unten links im Fenster befindet.
Schließlich wird die ContentView.AddSubview (ClickMeButton)
NSButton
Methode der Inhaltsansicht hinzugefügt, sodass 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, in der die Anzahl der NSButton
Klicks angezeigt wird:
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 nicht über ein bestimmtes Bezeichnungs-UI-Element verfügt, haben wir ein speziell formatiertes, nicht bearbeitbares NSTextField
Element hinzugefügt, das als Bezeichnung fungiert. Genau wie die Schaltfläche zuvor 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 der gleichen Position am oberen Rand des Fensters, wenn die Größe des Fensters vertikal geändert wird, und verkleinert und in der Breite vergrößert wird, während die Größe des Fensters horizontal geändert wird.
Auch hier fügt die ContentView.AddSubview (ClickMeLabel)
Methode der NSTextField
Inhaltsansicht hinzu, sodass sie beim Ausführen der Anwendung auf dem Bildschirm angezeigt und das Fenster geöffnet wird.
Anpassen des Fenstercontrollers
Da der Entwurf der Datei MainWindow
nicht mehr aus einer STORYBOARD- oder XIB-Datei geladen wird, müssen wir einige Anpassungen am Fenstercontroller vornehmen. Bearbeiten Sie die MainWindowController.cs Datei, 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 einem CGRect
. Genau wie das Koordinatensystem des Fensters definiert der Bildschirm (0,0) als untere linke Ecke. Als Nächstes definieren wir den Stil des Fensters mithilfe des Operators "Or ", 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 zum Schließen und kann geschlossen werden.
- Miniaturisierbar – Das Fenster verfügt über eine Miniaturgröße-Schaltfläche und kann minimiert werden.
- Größenänderung – Das Fenster verfügt über eine Schaltfläche zum Ändern der Größe und kann geändert werden.
- Hilfsprogramm : Das Fenster ist ein Hilfsprogramm-Stilfenster (Panel).
- DocModal – Wenn es sich bei dem Fenster um ein Panel handelt, handelt es sich um "Document Modal" anstelle von "System Modal".
- NonactivatingPanel – Wenn es sich bei dem Fenster um ein Panel handelt, wird es nicht zum Standard Fenster 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 in den Vollbildmodus wechseln.
- FullSizeContentView – Die Inhaltsansicht des Fensters befindet sich hinter dem Titel und dem Symbolleistenbereich.
Die letzten beiden Eigenschaften definieren den Puffertyp für das Fenster und wenn die Zeichnung des Fensters zurückgestellt wird. Weitere Informationen finden NSWindows
Sie in der Apple-Dokumentation zur Einführung in Windows .
Da das Fenster nicht aus einer Storyboard- oder XIB-Datei aufgeblasen wird, müssen wir es in unserer MainWindowController.cs simulieren, indem wir die Windows-Methode AwakeFromNib
aufrufen:
Window.AwakeFromNib ();
Auf diese Weise können Sie wie ein Standardfenster, das aus einer STORYBOARD- oder XIB-Datei geladen wird, mit Code für das Fenster codieren.
Anzeigen des Fensters
Wenn die STORYBOARD- oder XIB-Datei entfernt wurde und die MainWindow.cs und MainWindowController.cs Dateien geändert wurden, verwenden Sie das Fenster genauso wie jedes normale Fenster, das im Benutzeroberflächen-Generator von Xcode mit einer XIB-Datei erstellt wurde.
Im Folgenden wird eine neue Instanz des Fensters und des zugehörigen 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 die Schaltfläche ein paar Mal geklickt wurde, wird Folgendes angezeigt:
Hinzufügen eines Nur-Code-Fensters
Wenn wir nur einen Code hinzufügen möchten, xibless-Fenster zu einer vorhandenen Xamarin.Mac-Anwendung, klicken Sie mit der rechten Maustaste auf das Projekt im Projektmappenblock, und wählen Sie "Neue Datei hinzufügen>".. Wählen Sie im Dialogfeld "Neue Datei" die Option "Xamarin.Mac>Cocoa Window with Controller" aus, wie unten dargestellt:
Genau wie zuvor löschen wir die standardmäßige STORYBOARD- oder XIB-Datei aus dem Projekt (in diesem Fall SecondWindow.xib) und führen 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, kann es vorkommen, dass wir einem Fenster aus Code ein UI-Element hinzufügen möchten. Zum Beispiel:
var ClickMeButton = new NSButton (new CGRect (10, 10, 100, 30)){
AutoresizingMask = NSViewResizingMask.MinYMargin
};
MyWindow.ContentView.AddSubview (ClickMeButton);
Der obige Code erstellt ein neues NSButton
Element und fügt es zur Fensterinstanz für die MyWindow
Anzeige hinzu. Grundsätzlich kann jedes UI-Element, das im Schnittstellen-Generator 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 in Code 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 z. B. die AppDelegate.cs-Datei , 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 Code wird ein Statusleistenmenü erstellt und angezeigt, wenn die Anwendung gestartet wird. Weitere Informationen zum Arbeiten mit Menüs finden Sie in unserer Menüdokumentation .
Zusammenfassung
In diesem Artikel wird die Erstellung der Benutzeroberfläche einer Xamarin.Mac-Anwendung im C#-Code im Gegensatz zur Verwendung des Xcode-Schnittstellen-Generators mit .storyboard- oder XIB-Dateien beschrieben.