Xamarin.Mac 中的 Windows
本文介绍如何在 Xamarin.Mac 应用程序中使用窗口和面板。 它介绍如何在 Xcode 和 Interface Builder 中创建窗口和面板、从情节提要和 .xib 文件加载它们,以及以编程方式使用它们。
在 Xamarin.Mac 应用程序中使用 C# 和 .NET 时,你可以访问与开发人员 Objective-C 和 Xcode 相同的 Windows 和面板。 由于 Xamarin.Mac 与 Xcode 直接集成,因此可以使用 Xcode 的 Interface Builder 创建和维护 Windows 和面板 (,也可以选择直接在 C# 代码) 中创建它们。
根据目的,Xamarin.Mac 应用程序可以在屏幕上显示一个或多个 Windows,以管理和协调它显示和处理的信息。 窗口的主体函数包括:
- 提供可在其中放置和管理视图和控件的区域。
- 接受和响应事件,以响应用户与键盘和鼠标的交互。
Windows 可以在无模式状态 (使用,例如可以同时打开多个文档的文本编辑器) 或模式 ((例如,必须先关闭导出对话框),然后应用程序才能继续) 。
面板是一种特殊的 Window (基 NSWindow
类) 的子类,通常在应用程序中提供辅助功能,例如文本格式检查器和系统颜色选取器等实用工具窗口。
本文介绍在 Xamarin.Mac 应用程序中使用 Windows 和面板的基础知识。 强烈建议先完成 Hello, Mac 文章,特别是 Xcode 和接口生成器简介 以及 插座和操作 部分,因为它涵盖了我们将在本文中使用的关键概念和技术。
您可能还希望查看 Xamarin.Mac Internals 文档的公开 C# 类/方法Objective-C部分,其中介绍了Register
用于将 C# 类Objective-C连接到对象和 UI 元素的 和 Export
命令。
Windows 简介
如上所述,窗口提供了一个区域,可以在其中放置和管理视图和控件,并根据用户交互 (通过键盘或鼠标) 响应事件。
根据 Apple 的说法,macOS 应用中有五种main类型的 Windows:
- 文档窗口 - 文档窗口包含基于文件的用户数据,例如电子表格或文本文档。
- 应用窗口 - 应用窗口是非基于文档 (的应用程序的main窗口,如 Mac) 上的“日历”应用。
- 面板 - 面板浮动在其他窗口上方,并提供用户在打开文档时可以使用的工具或控件。 在某些情况下,面板可以是半透明的 (,例如处理大型图形) 。
- 对话框 - 对话框显示以响应用户操作,通常提供用户完成操作的方式。 对话框需要用户做出响应才能关闭。 (请参阅 使用对话框)
- 警报 - 警报是一种特殊类型的对话框,当发生严重问题 ((例如错误) )或警告 ((例如准备) 删除文件)时会出现。 由于警报是对话,因此还需要用户响应才能关闭警报。 (请参阅 使用警报)
有关详细信息,请参阅 Apple macOS 设计主题的“关于 Windows”部分。
主窗口、键窗口和非活动窗口
Xamarin.Mac 应用程序中的 Windows 的外观和行为可能会因用户当前与其交互的方式而有所不同。 用户当前关注的最重要文档或应用窗口称为 “主窗口”。 在大多数情况下,此窗口也是当前接受用户输入) 窗口 (键 窗口。 但并非总是如此,例如,颜色选取器可以打开,并且是用户与之交互的键窗口,以更改文档窗口中项的状态 (该窗口仍然是主窗口) 。
主窗口和密钥窗口 (如果它们是单独的) 始终处于活动状态, 则非活动窗口 是不在前台的打开窗口。 例如,文本编辑器应用程序一次可以打开多个文档,只有主窗口处于活动状态,所有其他窗口将处于非活动状态。
有关详细信息,请参阅 Apple macOS 设计主题的“关于 Windows”部分。
命名窗口
窗口可以显示标题栏,显示标题时,它通常是应用程序的名称、正在处理的文档的名称或窗口 (的功能,例如 Inspector) 。 某些应用程序不显示标题栏,因为它们可通过视觉识别,并且不适用于文档。
Apple 建议遵循以下准则:
- 使用应用程序名称作为main非文档窗口的标题。
- 将新文档窗口
untitled
命名为 。 对于第一个新文档,不要将数字追加到标题 (,例如untitled 1
) 。 如果用户在保存并命名第一个文档之前创建另一个新文档,请调用该窗口untitled 2
、untitled 3
等。
有关详细信息,请参阅 Apple macOS 设计主题的命名 Windows 部分。
全屏窗口
在 macOS 中,应用程序的窗口可以全屏隐藏所有内容,包括应用程序菜单栏 (可以通过将光标移动到屏幕顶部) 来显示,以提供与其内容的无干扰交互。
Apple 建议遵循以下准则:
- 确定窗口全屏是否有意义。 提供简短交互 (的应用程序(如计算器) )不应提供全屏模式。
- 如果全屏任务需要工具栏,则显示工具栏。 通常,工具栏在全屏模式下处于隐藏状态。
- 全屏窗口应具有用户完成任务所需的所有功能。
- 如果可能,请在用户处于全屏窗口中时避免 Finder 交互。
- 利用增加的屏幕空间,而无需将焦点从main任务移开。
有关详细信息,请参阅 Apple macOS 设计主题的全屏 Windows 部分。
面板
面板是一个辅助窗口,其中包含影响活动文档或选择 ((例如系统颜色选取器) )的控件和选项:
面板可以是 特定于应用 或 系统范围的。 App-Specific面板浮动在应用程序的文档窗口顶部,当应用程序在后台时会消失。 系统范围的面板 (,如 字体 面板) ,浮动在所有打开的窗口顶部,无论应用程序如何。
Apple 建议遵循以下准则:
- 一般情况下,使用标准面板,透明面板仅应谨慎使用,并且用于图形密集型任务。
- 请考虑使用面板让用户轻松访问直接影响其任务的重要控件或信息。
- 根据需要隐藏和显示面板。
- 面板应始终包含标题栏。
- 面板不应包含活动最小化按钮。
检查器
大多数新式 macOS 应用程序将影响活动文档或选择的辅助控件和选项作为主窗口 (的 检查器 提供,如下面所示的 “页面” 应用) ,而不是使用面板 Windows:
有关详细信息,请参阅 Apple macOS 设计主题的面板部分和我们的 MacInspector 示例应用,了解 Xamarin.Mac 应用中检查器接口的完整实现。
在 Xcode 中创建和维护窗口
创建新的 Xamarin.Mac Cocoa 应用程序时,默认情况下会获得标准空白窗口。 此窗口在 .storyboard
项目中自动包含的文件中定义。 若要编辑 Windows 设计,请在解决方案资源管理器中双击Main.storyboard
文件:
这将在 Xcode 的接口生成器中打开窗口设计:
在 属性检查器中,可以使用多个属性来定义和控制窗口:
- 标题 - 这是将在窗口标题栏中显示的文本。
- 自动保存 - 这是在窗口位置和设置自动保存时用于标识窗口的 键 。
- 标题栏 - 窗口是否显示标题栏。
- 统一标题和工具栏 - 如果窗口包含工具栏,应为标题栏的一部分。
- 完整大小的内容视图 - 允许窗口的内容区域位于标题栏下。
- 阴影 - 窗口是否具有阴影。
- 纹理 - 纹理窗口可以使用效果 ((如活力) )并且可以通过拖动其正文上的任意位置来移动。
- 关闭 - 窗口是否具有“关闭”按钮。
- 最小化 - 窗口是否具有最小化按钮。
- 调整大小 - 窗口是否具有调整大小控件。
- 工具栏按钮 - 窗口是否具有隐藏/显示工具栏按钮。
- 可还原 - 窗口的位置和设置是否自动保存和还原。
- 启动时可见 - 加载文件时自动显示的
.xib
窗口。 - 停用时隐藏 - 当应用程序进入后台时,窗口处于隐藏状态。
- 关闭时释放 - 窗口在关闭时从内存中清除。
- 始终显示工具提示 - 工具提示是否不断显示。
- 重新计算视图循环 - 在绘制窗口之前重新计算视图顺序。
- 空间、 公开 和 循环 - 全部定义窗口在这些 macOS 环境中的行为方式。
- 全屏 - 确定此窗口是否可以进入全屏模式。
- 动画 - 控制可用于窗口的动画类型。
- 外观 - 控制窗口的外观。 目前只有一个外观,水。
有关更多详细信息,请参阅 Apple 的 Windows 和 NSWindow简介文档。
设置默认大小和位置
若要设置窗口的初始位置并控制窗口的大小,请切换到 “大小检查器”:
在这里,可以设置窗口的初始大小,为其指定最小和最大大小,在屏幕上设置初始位置,并控制窗口周围的边框。
设置自定义main窗口控制器
为了能够创建输出口和操作以向 C# 代码公开 UI 元素,Xamarin.Mac 应用需要使用自定义窗口控制器。
请执行以下操作:
在 Xcode 的 Interface Builder 中打开应用的情节提要。
在
NSWindowController
设计图面中选择 。切换到 “标识检查器” 视图,输入
WindowController
作为 “类名”:保存更改并返回到Visual Studio for Mac进行同步。
文件
WindowController.cs
将添加到项目中Visual Studio for Mac解决方案资源管理器:在 Xcode 的 Interface Builder 中重新打开情节提要。
该文件
WindowController.h
将可供使用:
添加 UI 元素
若要定义窗口的内容,请将控件从 库检查器 拖到 接口编辑器上。 有关使用接口生成器创建和启用控件的详细信息 ,请参阅我们的 Xcode 和 Interface Builder 简介 文档。
例如,将工具栏从 库检查器 拖动到 “接口编辑器”中的窗口中:
接下来,在 “文本视图” 中拖动并调整其大小以填充工具栏下的区域:
由于我们希望 文本视图 随着窗口大小的变化而缩小和增长,因此让我们切换到 约束编辑器 并添加以下约束:
通过单击编辑器顶部的四个 红色 I 形梁 并单击“ 添加 4 个约束”,我们告知文本视图坚持给定的 X、Y 坐标,并在调整窗口大小时水平和垂直方向增长或收缩。
最后,使用输出口 (确保选择ViewController.h
文件) 向代码公开文本视图:
保存更改并切换回 Visual Studio for Mac 以与 Xcode 同步。
有关使用 输出口 和 操作的详细信息,请参阅输出 口和操作 文档。
标准窗口工作流
对于在 Xamarin.Mac 应用程序中创建和使用的任何窗口,此过程与上面刚刚完成的过程基本相同:
- 对于不是默认自动添加到项目的新窗口,请向项目添加新的窗口定义。 下面将详细介绍这一点。
- 双击
Main.storyboard
文件以打开在 Xcode 的 Interface Builder 中编辑的窗口设计。 - 将新窗口拖动到用户界面的设计中,并使用 Segues (将窗口挂钩到主窗口,有关详细信息,请参阅使用情节提要文档) 的 Segues 部分。
- 在属性检查器和大小检查器中设置任何必需的窗口属性。
- 拖入生成接口所需的控件,并在 属性检查器中对其进行配置。
- 使用 大小检查器 处理 UI 元素的大小调整。
- 通过 输出口 和 操作向 C# 代码公开窗口的 UI 元素。
- 保存更改并切换回 Visual Studio for Mac 以与 Xcode 同步。
创建基本窗口后,我们将查看 Xamarin.Mac 应用程序在使用窗口时执行的典型过程。
显示默认窗口
默认情况下,新的 Xamarin.Mac 应用程序会在启动时自动显示文件中定义的 MainWindow.xib
窗口:
由于我们修改了上述窗口的设计,因此它现在包含默认的工具栏和 文本视图 控件。 文件中的 Info.plist
以下部分负责显示此窗口:
主界面下拉列表用于选择将用作main应用 UI (的情节提要,在本例Main.storyboard
中) 。
视图控制器会自动添加到项目中,以控制 (显示的主窗口及其主视图) 。 它在 文件中定义ViewController.cs
,并附加到标识检查器下的接口生成器中的文件所有者:
对于我们的窗口,我们希望它在首次打开时具有 的标题 untitled
,因此让我们重写 ViewWillAppear
中的 ViewController.cs
方法,如下所示:
public override void ViewWillAppear ()
{
base.ViewWillAppear ();
// Set Window Title
this.View.Window.Title = "untitled";
}
注意
窗口的 Title
属性是在 方法而不是 方法中 ViewWillAppear
设置的 ViewDidLoad
,因为虽然视图可能已加载到内存中,但它尚未完全实例化。 在 Title
方法中 ViewDidLoad
访问 属性时,我们会收到异常 null
,因为尚未构造窗口并将其连接到 属性。
以编程方式关闭窗口
有时你可能希望以编程方式关闭 Xamarin.Mac 应用程序中的窗口,而不是让用户单击窗口的 “关闭 ”按钮或使用菜单项。 macOS 提供了两种不同的以编程方式关闭 的方法 NSWindow
: PerformClose
和 Close
。
PerformClose
PerformClose
调用 的 NSWindow
方法模拟用户单击窗口的“关闭”按钮,方法是暂时突出显示按钮,然后关闭窗口。
如果应用程序实现 NSWindow
的 WillClose
事件,则会在关闭窗口之前引发该事件。 如果事件返回 false
,则不会关闭窗口。 如果窗口没有 “关闭 ”按钮或由于任何原因而无法关闭,则 OS 将发出警报声音。
例如:
MyWindow.PerformClose(this);
将尝试关闭 MyWindow
NSWindow
实例。 如果成功,窗口将关闭,否则将发出警报声音,并保持打开状态。
关闭
Close
调用 的 NSWindow
方法不会模拟用户通过暂时突出显示按钮来单击窗口的“关闭”按钮,而只是关闭窗口。
窗口不必可见,关闭 NSWindowWillCloseNotification
窗口时,通知将发布到默认通知中心以关闭窗口。
方法 Close
与 方法在两个重要方面 PerformClose
不同:
- 它不会尝试引发
WillClose
事件。 - 它不会通过暂时突出显示按钮来模拟用户单击 “关闭 ”按钮。
例如:
MyWindow.Close();
将关闭 MyWindow
NSWindow
实例。
修改的窗口内容
在 macOS 中,Apple 提供了一种通知用户 Windows (NSWindow
) 的内容已被用户修改并需要保存的方法。 如果窗口包含修改后的内容,则会在“ 关闭 ”小组件中显示一个小黑点:
如果用户尝试关闭窗口或退出 Mac 应用,而窗口的内容存在未保存的更改,则应显示 对话框 或 模式工作表 ,并允许用户首先保存其更改:
将窗口标记为已修改
若要将窗口标记为已修改内容,请使用以下代码:
// Mark Window content as modified
Window.DocumentEdited = true;
保存更改后,使用以下命令清除修改后的标志:
// Mark Window content as not modified
Window.DocumentEdited = false;
在关闭窗口之前保存更改
若要为关闭 Window 的用户watch并允许他们事先保存修改后的内容,需要创建 的NSWindowDelegate
子类并重写其 WindowShouldClose
方法。 例如:
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
}
}
使用以下代码将此委托的实例附加到窗口:
// Set delegate
Window.Delegate = new EditorWindowDelegate(Window);
在关闭应用之前保存更改
最后,Xamarin.Mac 应用应检查,以查看其任何 Windows 是否包含已修改的内容,并允许用户在退出之前保存更改。 为此,请 AppDelegate.cs
编辑文件,重写 ApplicationShouldTerminate
方法并使其如下所示:
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;
}
使用多个窗口
大多数基于文档的 Mac 应用程序可以同时编辑多个文档。 例如,文本编辑器可以同时打开多个要编辑的文本文件。 默认情况下,新的 Xamarin.Mac 应用程序具有“文件”菜单,其中“新建项”自动连接到操作newDocument:
。
下面的代码将激活此新项目,并允许用户打开主窗口的多个副本,以一次编辑多个文档。
编辑 文件并 AppDelegate.cs
添加以下计算属性:
public int UntitledWindowCount { get; set;} =1;
使用它来跟踪未保存的文件数,以便我们可以根据上述) 所述的 Apple 指南向用户提供反馈 (。
接下来,添加以下方法:
[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);
}
此代码创建新版本的窗口控制器,加载新窗口,使其成为主窗口和键窗口,并设置标题。 现在,如果我们运行应用程序,并从“文件”菜单中选择“新建”,则会打开并显示新的编辑器窗口:
如果我们打开 Windows 菜单,你可以看到应用程序正在自动跟踪和处理打开的窗口:
有关在 Xamarin.Mac 应用程序中使用菜单的详细信息,请参阅使用 菜单 文档。
获取当前活动窗口
在可以打开多个窗口 (文档) 的 Xamarin.Mac 应用程序中,有时需要获取当前最顶部的窗口 (关键窗口) 。 以下代码将返回键窗口:
var window = NSApplication.SharedApplication.KeyWindow;
可以在需要访问当前键窗口的任何类或方法中调用它。 如果当前没有打开任何窗口,它将返回 null
。
访问所有应用窗口
有时可能需要访问 Xamarin.Mac 应用当前已打开的所有窗口。 例如,查看用户想要打开的文件是否已在退出窗口中打开。
NSApplication.SharedApplication
维护一个 Windows
属性,该属性包含应用中所有打开的窗口的数组。 可以循环访问此数组以访问应用的所有当前窗口。 例如:
// 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;
}
}
在示例代码中,我们将每个返回的窗口强制转换为应用中的自定义 ViewController
类,并针对用户想要打开的文件的路径测试自定义 Path
属性的值。 如果文件已打开,则会将窗口置于前面。
在代码中调整窗口大小
有时,应用程序需要在代码中调整窗口的大小。 若要调整窗口的大小并重新定位窗口,请调整它的 Frame
属性。 调整窗口的大小时,通常还需要调整其原点,以便由于 macOS 的坐标系,使窗口保持在同一位置。
与左上角表示 (0,0) 的 iOS 不同,macOS 使用数学坐标系,其中屏幕左下角表示 (0,0) 。 在 iOS 中,坐标随着向右向下移动而增加。 在 macOS 中,坐标值向上向右增加。
以下示例代码调整窗口的大小:
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);
重要
在代码中调整窗口大小和位置时,需要确保遵循在 Interface Builder 中设置的最小和最大大小。 这不会自动执行,并且你将能够使窗口大于或小于这些限制。
监视窗口大小更改
有时可能需要监视 Xamarin.Mac 应用内窗口大小的更改。 例如,重绘内容以适应新大小。
若要监视大小更改,请先确保已在 Xcode 的 Interface Builder 中为窗口控制器分配自定义类。 例如, MasterWindowController
在以下代码中:
接下来,编辑自定义窗口控制器类并监视 DidResize
控制器窗口上的事件,以便收到实时大小更改的通知。 例如:
public override void WindowDidLoad ()
{
base.WindowDidLoad ();
Window.DidResize += (sender, e) => {
// Do something as the window is being live resized
};
}
(可选)可以使用 DidEndLiveResize
事件仅在用户完成窗口大小更改后收到通知。 例如:
public override void WindowDidLoad ()
{
base.WindowDidLoad ();
Window.DidEndLiveResize += (sender, e) => {
// Do something after the user's finished resizing
// the window
};
}
设置窗口的标题和表示的文件
使用表示文档的窗口时, 具有一个 DocumentEdited
属性,NSWindow
如果设置为 true
,则会在“关闭”按钮中显示一个小点,以指示文件已修改,应在关闭前保存。
让我们编辑 ViewController.cs
文件并进行以下更改:
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;
};
}
我们还在监视 WillClose
窗口中的事件并检查 属性的状态 DocumentEdited
。 如果是这样, true
我们需要让用户能够保存对文件的更改。 如果我们运行应用并输入一些文本,将显示点:
如果尝试关闭窗口,将收到警报:
如果要从文件加载文档,请使用方法将窗口的标题设置为文件名 window.SetTitleWithRepresentedFilename (Path.GetFileName(path));
, (给定 path
表示) 打开的文件的字符串。 此外,可以使用 方法设置文件的 window.RepresentedUrl = url;
URL。
如果 URL 指向 OS 已知的文件类型,其图标将显示在标题栏中。 如果用户右键单击图标,将显示文件的路径。
AppDelegate.cs
编辑 文件并添加以下方法:
[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;
}
}
}
现在,如果我们运行应用,请从“文件”菜单中选择“打开...”,从“打开”对话框中选择一个文本文件并将其打开:
将显示文件,并使用文件的图标设置标题:
向项目添加新窗口
除了main文档窗口之外,Xamarin.Mac 应用程序可能需要向用户显示其他类型的窗口,例如“首选项”或“检查器面板”。
若要添加新窗口,请执行以下操作:
在解决方案资源管理器,双击
Main.storyboard
该文件以在 Xcode 的 Interface Builder 中将其打开进行编辑。从库中拖动新的窗口控制器,并将其拖放到设计图面上:
在 标识检查器中,输入
PreferencesWindow
作为 情节提要 ID:设计接口:
打开“应用菜单” (
MacWindows
) ,选择 “首选项...”,Control-Click并拖动到新窗口:从弹出菜单中选择“ 显示 ”。
保存更改并返回到 Visual Studio for Mac 以与 Xcode 同步。
如果我们运行代码并从“应用程序”菜单中选择“首选项...”,则会显示窗口:
使用面板
如本文开头所述,面板浮动在其他窗口上方,并提供用户在打开文档时可以使用的工具或控件。
与在 Xamarin.Mac 应用程序中创建和使用的任何其他类型的窗口一样,该过程基本相同:
- 向项目添加新的窗口定义。
- 双击
.xib
文件以打开在 Xcode 的 Interface Builder 中编辑的窗口设计。 - 在属性检查器和大小检查器中设置任何必需的窗口属性。
- 拖入生成接口所需的控件,并在 属性检查器中对其进行配置。
- 使用 大小检查器 处理 UI 元素的大小调整。
- 通过 输出口 和 操作向 C# 代码公开窗口的 UI 元素。
- 保存更改并切换回 Visual Studio for Mac 以与 Xcode 同步。
在 属性检查器中,有以下特定于面板的选项:
- 样式 - 允许你调整面板的样式:常规面板 (看起来像标准窗口) ,实用工具面板 (具有较小的标题栏) ,HUD 面板 (半透明,标题栏是背景) 的一部分。
- 未激活 - 面板中的“确定”成为关键窗口。
- 文档模式 - 如果文档模式,面板将仅浮动在应用程序窗口上方,否则它浮动在全部之上。
若要添加新面板,请执行以下操作:
在解决方案资源管理器中,右键单击“项目”,然后选择“添加新>文件...”。
在“新建文件”对话框中,选择“带控制器的Xamarin.Mac> Cocoa 窗口”:
对“名称”输入
DocumentPanel
,然后单击“新建”按钮。双击
DocumentPanel.xib
文件以将其打开,以便在 Interface Builder 中编辑:删除现有窗口,并从“接口编辑器”中的“库检查器”拖动面板:
将面板挂钩到 “文件所有者 - ”窗口 - 的“输出口”:
切换到 标识检查器 ,并将 Panel 的 类设置为
DocumentPanel
:保存更改并返回到 Visual Studio for Mac 以与 Xcode 同步。
编辑 文件并将
DocumentPanel.cs
类定义更改为以下内容:public partial class DocumentPanel : NSPanel
保存对文件所做的更改。
AppDelegate.cs
编辑 文件,使 DidFinishLaunching
方法如下所示:
public override void DidFinishLaunching (NSNotification notification)
{
// Display panel
var panel = new DocumentPanelController ();
panel.Window.MakeKeyAndOrderFront (this);
}
如果运行应用程序,将显示面板:
重要
Apple 已弃用面板 Windows,应将其替换为 检查器接口。 有关在 Xamarin.Mac 应用中创建 Inspector 的完整示例,请参阅 MacInspector 示例应用。
总结
本文详细介绍了在 Xamarin.Mac 应用程序中使用 Windows 和面板。 我们了解了 Windows 和面板的不同类型和用法,如何在 Xcode 的 Interface Builder 中创建和维护 Windows 和面板,以及如何在 C# 代码中使用 Windows 和面板。