Конструктор пользовательского интерфейса .storyboard/.xib-less в Xamarin.Mac
В этой статье описывается создание пользовательского интерфейса приложения Xamarin.Mac непосредственно из кода C# без файлов раскадровки, XIB-файлов или построителя интерфейсов.
Обзор
При работе с C# и .NET в приложении Xamarin.Mac у вас есть доступ к тем же элементам пользовательского интерфейса и средствам, в которых работает Objective-C разработчик, и Xcode . Как правило, при создании приложения Xamarin.Mac вы будете использовать построитель интерфейсов Xcode с раскадровкой или XIB-файлами для создания и поддержания пользовательского интерфейса приложения.
Вы также можете создавать некоторые или все пользовательские интерфейсы приложения Xamarin.Mac непосредственно в коде C#. В этой статье мы рассмотрим основы создания пользовательских интерфейсов и элементов пользовательского интерфейса в коде C#.
Переключение окна на использование кода
При создании нового приложения Xamarin.Mac Cocoa вы получаете стандартное пустое окно по умолчанию. Эти окна определяются в файле Main.storyboard (или традиционно в файле MainWindow.xib), который автоматически включается в проект. Это также включает в себя файл ViewController.cs , который управляет основным представлением приложения (или снова традиционно MainWindow.cs и файлом MainWindowController.cs ).
Чтобы перейти к окну Xibless для приложения, выполните следующие действия.
Откройте приложение, которое вы хотите прекратить использовать
.storyboard
или XIB-файлы, чтобы определить пользовательский интерфейс в Visual Studio для Mac.На панели решений щелкните правой кнопкой мыши файл Main.storyboard или MainWindow.xib и выберите "Удалить".
В диалоговом окне "Удалить" нажмите кнопку "Удалить", чтобы полностью удалить раскадровку или XIB из проекта:
Теперь необходимо изменить файл MainWindow.cs, чтобы определить макет окна и изменить файл ViewController.cs или MainWindowController.cs, чтобы создать экземпляр классаMainWindow
, так как мы больше не используем раскадровку или XIB-файл.
Современные приложения Xamarin.Mac, использующие раскадровки для пользовательского интерфейса, могут не включать файлы MainWindow.cs, ViewController.cs или MainWindowController.cs . По мере необходимости просто добавьте в проект новый пустой класс C# (добавить>новый файл...>Общий>пустой класс) и назовите его таким же, как отсутствующий файл.
Определение окна в коде
Затем измените файл MainWindow.cs и сделайте его следующим образом:
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
}
}
Давайте обсудим несколько ключевых элементов.
Во-первых, мы добавили несколько вычисляемых свойств , которые будут действовать как точки (как если бы окно было создано в раскадровке или XIB-файле):
public NSButton ClickMeButton { get; set;}
public NSTextField ClickMeLabel { get ; set;}
Они помогут нам получить доступ к элементам пользовательского интерфейса, которые будут отображаться в окне. Так как окно не раздувается из раскадровки или XIB-файла, нам нужен способ создания экземпляра MainWindowController
(как мы увидим далее в классе). Вот что делает этот новый метод конструктора:
public MainWindow(CGRect contentRect, NSWindowStyle aStyle, NSBackingStore bufferingType, bool deferCreation): base (contentRect, aStyle,bufferingType,deferCreation) {
...
}
Здесь мы создадим макет окна и поместим все элементы пользовательского интерфейса, необходимые для создания требуемого пользовательского интерфейса. Прежде чем добавлять элементы пользовательского интерфейса в окно, он должен содержать элементы в представлении содержимого:
ContentView = new NSView (Frame);
При этом создается представление содержимого, которое заполняет окно. Теперь мы добавим первый элемент пользовательского интерфейса , в NSButton
окно:
ClickMeButton = new NSButton (new CGRect (10, Frame.Height-70, 100, 30)){
AutoresizingMask = NSViewResizingMask.MinYMargin
};
ContentView.AddSubview (ClickMeButton);
Первое, что следует отметить здесь, заключается в том, что в отличие от iOS, macOS использует математические нотации для определения системы координат окна. Таким образом, точка источника находится в левом нижнем углу окна, со значениями справа и в правом верхнем углу окна. При создании нового NSButton
мы учитываем это, как мы определяем его положение и размер на экране.
Свойство AutoresizingMask = NSViewResizingMask.MinYMargin
сообщает кнопке, что она будет оставаться в том же расположении в верхней части окна, когда окно изменяется по вертикали. Опять же, это необходимо, так как (0,0) находится в нижней левой части окна.
Наконец, метод добавляет NSButton
в представление содержимого, ContentView.AddSubview (ClickMeButton)
чтобы оно отображалось на экране при запуске приложения и окне.
Затем в окно добавляется метка, в которую будет отображаться количество щелчков NSButton
:
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);
Так как macOS не имеет определенного элемента пользовательского интерфейса Label , мы добавили специально стильную, не редактируемую NSTextField
для действия в качестве метки. Как и кнопка раньше, размер и расположение учитывает, что (0,0) находится в нижней левой части окна. Свойство AutoresizingMask = NSViewResizingMask.WidthSizable | NSViewResizingMask.MinYMargin
использует или оператор для объединения двух NSViewResizingMask
функций. Это приведет к тому, что метка остается в том же расположении в верхней части окна, когда окно изменяется по вертикали и увеличивается по ширине, так как окно изменяется по горизонтали.
Опять же, метод добавляет NSTextField
в представление содержимого, ContentView.AddSubview (ClickMeLabel)
чтобы он отображался на экране при запуске приложения и открываемом окне.
Настройка контроллера окна
Так как дизайн больше не загружается из раскадровки MainWindow
или XIB-файла, нам потребуется внести некоторые изменения в контроллер окна. Измените файл MainWindowController.cs и сделайте его следующим образом:
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; }
}
}
}
Давайте обсудим ключевые элементы этого изменения.
Сначала мы определим новый экземпляр MainWindow
класса и назначим его свойству базового контроллера Window
окна:
CGRect contentRect = new CGRect (0, 0, 1000, 500);
base.Window = new MainWindow(contentRect, (NSWindowStyle.Titled | NSWindowStyle.Closable | NSWindowStyle.Miniaturizable | NSWindowStyle.Resizable), NSBackingStore.Buffered, false);
Мы определяем расположение окна экрана с помощью .CGRect
Как и система координат окна, экран определяет (0,0) в левом нижнем углу. Далее мы определим стиль окна с помощью оператора Or для объединения двух или нескольких NSWindowStyle
функций:
... (NSWindowStyle.Titled | NSWindowStyle.Closable | NSWindowStyle.Miniaturizable | NSWindowStyle.Resizable) ...
Доступны следующие NSWindowStyle
функции:
- Без границы — окно не будет иметь границы.
- Заголовок — окно будет иметь строку заголовка.
- Closable — окно имеет кнопку закрытия и может быть закрыта.
- Минимализируемый — окно имеет кнопку миниатуризации и может быть свернута.
- Можно изменить размер. Окно будет иметь кнопку изменения размера и изменить размер.
- Служебная программа — это окно стиля служебной программы (панель).
- DocModal — если окно является панелью, она будет модальным документом вместо модала системы.
- NonactivatingPanel — если окно является панелью, она не будет выполнена в главном окне.
- TexturedBackground — окно будет иметь текстурированный фон.
- Немасштабированное — окно не будет масштабироваться.
- UnifiedTitleAndToolbar — области заголовка окна и панели инструментов будут присоединены.
- Hud — окно будет отображаться как панель отображения головы.
- FullScreenWindow — окно может входить в полноэкранный режим.
- FullSizeContentView — представление содержимого окна находится за заголовком и областью панели инструментов.
Последние два свойства определяют тип буферизации для окна и если рисунок окна будет отложен. Дополнительные сведения NSWindows
см. в документации Apple по Windows .
Наконец, так как окно не раздувается из раскадровки или XIB-файла, необходимо имитировать его в нашем MainWindowController.cs путем вызова метода Windows AwakeFromNib
:
Window.AwakeFromNib ();
Это позволит кодировать окно так же, как стандартное окно, загруженное из раскадровки или XIB-файла.
Отображение окна
При удалении раскадровки или XIB-файла и изменения MainWindow.cs и MainWindowController.cs-файлов вы будете использовать окно так же, как и любое нормальное окно, созданное в построителе интерфейсов Xcode с Xcode с Xcode-файлом.
Ниже будет создан новый экземпляр окна и его контроллера и отобразится окно на экране:
private MainWindowController mainWindowController;
...
mainWindowController = new MainWindowController ();
mainWindowController.Window.MakeKeyAndOrderFront (this);
На этом этапе, если приложение запущено, а кнопка щелкнула пару раз, отобразится следующее:
Добавление только окна кода
Если мы хотим добавить только код, окно xibless в существующее приложение Xamarin.Mac, щелкните правой кнопкой мыши проект на панели решения и выберите "Добавить>новый файл..". В диалоговом окне "Создать файл" выберите окно Xamarin.Mac>Cocoa с контроллером, как показано ниже:
Как и раньше, мы удалим файл раскадровки по умолчанию или XIB-файла из проекта (в данном случае SecondWindow.xib) и выполните действия, описанные в разделе "Переключение окна", чтобы использовать приведенный выше раздел "Код " для покрытия определения окна для кода.
Добавление элемента пользовательского интерфейса в окно в коде
Если окно было создано в коде или загружено из раскадровки или XIB-файла, иногда требуется добавить элемент пользовательского интерфейса в окно из кода. Например:
var ClickMeButton = new NSButton (new CGRect (10, 10, 100, 30)){
AutoresizingMask = NSViewResizingMask.MinYMargin
};
MyWindow.ContentView.AddSubview (ClickMeButton);
Приведенный выше код создает новый NSButton
и добавляет его в MyWindow
экземпляр окна для отображения. В основном любой элемент пользовательского интерфейса, который можно определить в конструкторе интерфейсов Xcode в раскадровки или XIB-файле, можно создать в коде и отобразить в окне.
Определение строки меню в коде
Из-за текущих ограничений в Xamarin.Mac не рекомендуется создавать строку меню приложения Xamarin.Mac,NSMenuBar
но продолжать использовать файл Main.storyboard или MainMenu.xib для его определения. Таким образом, вы можете добавлять и удалять меню и элементы меню в коде C#.
Например, измените файл AppDelegate.cs и сделайте DidFinishLaunching
метод следующим:
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);
}
В приведенном выше меню "Строка состояния" создается из кода и отображается при запуске приложения. Дополнительные сведения о работе с меню см. в нашей документации по меню.
Итоги
В этой статье подробно рассматривается создание пользовательского интерфейса приложения Xamarin.Mac в коде C# в отличие от использования конструктора интерфейсов Xcode с раскадровкой или Xib-файлами.