对话框控件
对话框控件是用于提供上下文应用信息的模式 UI 覆盖。 除非显式取消这些控件,否则它们会阻止与应用窗口的交互。 它们通常会请求用户进行某种类型的操作。
这是正确的控件吗?
使用对话框通知用户重要信息或在可以完成某个操作之前请求确认或其他信息。
有关何时使用对话框以及何时使用浮出控件(类似控件)的建议,请参阅对话框和浮出控件。
一般指南
- 在对话文本的第一行中清楚地确定问题或用户的目标。
- 对话框标题是主要指令,是可选的。
- 使用简短标题来解释用户对对话需要执行的操作。
- 如果使用对话框传递简单的消息、错误或问题,可以选择省略标题。 依靠内容文本传送该核心信息。
- 确保游戏与按钮选项直接相关。
- 对话框内容包含描述性文本,并且是必需的。
- 尽可能简单地显示消息、错误或阻止问题。
- 如果使用对话框标题,请使用内容区域提供更多详细信息或定义术语。 不要用略有不同的措辞重复标题。
- 必须至少显示一个对话框按钮。
- 确保你的对话框至少有一个按钮对应于安全、没有破坏性的操作,如“明白了!”、“关闭”或“取消”。 使用 CloseButton API 可添加该按钮。
- 使用主要说明或内容的特定响应作为按钮文本。 例如,“是否允许 AppName 访问你的位置?”,后跟“允许”和“阻止”按钮。 可以更快地理解特定响应,从而做出高效的决策。
- 确保操作按钮的文本保持简明。 简短的字符串使用户能够快速、自信地做出选择。
- 除了安全、无破坏性的操作外,你还可以选择为用户提供一个或两个与主要说明相关的操作按钮。 这些“执行”操作按钮用于确认对话框的重点。 使用 PrimaryButton 和 SecondaryButton API 可添加这些“执行”操作。
- “执行”操作按钮应显示为最左侧按钮。 安全、无破坏性的操作应显示为最右侧的按钮。
- 可以选择三个按钮之一作为对话框的默认按钮。 使用 DefaultButton API 可区分其中一个按钮。
- 不要将对话框用于与页面上特定位置相关的错误,例如验证错误(例如,在密码字段中),使用应用的画布本身显示内联错误。
- 使用 ContentDialog 类生成对话框体验。 不要使用已弃用的 MessageDialog API。
UWP 和 WinUI 2
重要
本文中的信息和示例是针对使用 Windows App SDK 和 WinUI 3 的应用优化的,但通常适用于使用 WinUI 2 的 UWP 应用。 有关特定于平台的信息和示例,请查看 UWP API 参考。
本部分包含在 UWP 或 WinUI 2 应用中使用该控件所需的信息。
此控件的 API 存在于 Windows.UI.Xaml.Controls 命名空间中。
- UWP API:ContentDialog 类
- 打开 WinUI 2 库应用并查看 ContentDialog 的操作。 WinUI 2 库应用包括大多数 WinUI 2 控件、特性和功能的交互式示例。 通过 Microsoft Store 获取应用,或在 GitHub 上获取源代码。
建议使用最新的 WinUI 2 来获取所有控件的最新样式和模板。 WinUI 2.2 或更高版本包含此控件的使用圆角的新模板。 有关详细信息,请参阅圆角半径。
创建对话框
- 重要 API: ContentDialog 类
WinUI 3 库应用包括大多数 WinUI 3 控件、特性和功能的交互式示例。 通过 Microsoft Store 获取应用,或在 GitHub 上获取源代码
若要创建对话框,请使用 ContentDialog 类。 可以在代码或标记中创建对话框。 尽管在 XAML 中定义 UI 元素通常更容易,但在简单对话框中,它实际上更容易使用代码。 本示例创建一个对话框,通知用户没有 WiFi 连接,然后使用 ShowAsync 方法显示它。
private async void DisplayNoWifiDialog()
{
ContentDialog noWifiDialog = new ContentDialog
{
Title = "No wifi connection",
Content = "Check your connection and try again.",
CloseButtonText = "OK"
};
ContentDialogResult result = await noWifiDialog.ShowAsync();
}
当用户单击对话框按钮时,ShowAsync 方法将返回 ContentDialogResult,告知用户单击哪个按钮。
此示例中的对话框提出问题,并使用返回 的 ContentDialogResult 来确定用户的响应。
private async void DisplayDeleteFileDialog()
{
ContentDialog deleteFileDialog = new ContentDialog
{
Title = "Delete file permanently?",
Content = "If you delete this file, you won't be able to recover it. Do you want to delete it?",
PrimaryButtonText = "Delete",
CloseButtonText = "Cancel"
};
ContentDialogResult result = await deleteFileDialog.ShowAsync();
// Delete the file if the user clicked the primary button.
/// Otherwise, do nothing.
if (result == ContentDialogResult.Primary)
{
// Delete the file.
}
else
{
// The user clicked the CloseButton, pressed ESC, Gamepad B, or the system back button.
// Do nothing.
}
}
提供安全操作
由于对话框会阻止用户交互,而且按钮是用户消除对话框的主要机制,因此请确保你的对话框至少包含一个“安全”且无破坏性的按钮,如“关闭”或“明白!”。 所有对话应都至少应包含一个安全操作按钮来关闭对话框。 这可以确保用户能自信地关闭对话框,而未执行操作。
private async void DisplayNoWifiDialog()
{
ContentDialog noWifiDialog = new ContentDialog
{
Title = "No wifi connection",
Content = "Check your connection and try again.",
CloseButtonText = "OK"
};
ContentDialogResult result = await noWifiDialog.ShowAsync();
}
当对话框用于显示阻止问题时,你的对话框应向用户显示与该问题相关的操作按钮。 这个“安全”且无破坏性的按钮可能会伴随一个或两个“执行”操作按钮。 在向用户提供多个选项时,请确保按钮可清晰地说明与所提出问题相关的“执行”和安全的“不执行”操作。
private async void DisplayLocationPromptDialog()
{
ContentDialog locationPromptDialog = new ContentDialog
{
Title = "Allow AppName to access your location?",
Content = "AppName uses this information to help you find places, connect with friends, and more.",
CloseButtonText = "Block",
PrimaryButtonText = "Allow"
};
ContentDialogResult result = await locationPromptDialog.ShowAsync();
}
向用户提供两个“执行”操作和一个“不执行”操作时,可以使用三个按钮对话框。 应慎用三个按钮对话框,辅助操作与安全/关闭操作之间应有清晰的区别。
private async void DisplaySubscribeDialog()
{
ContentDialog subscribeDialog = new ContentDialog
{
Title = "Subscribe to App Service?",
Content = "Listen, watch, and play in high definition for only $9.99/month. Free to try, cancel anytime.",
CloseButtonText = "Not Now",
PrimaryButtonText = "Subscribe",
SecondaryButtonText = "Try it"
};
ContentDialogResult result = await subscribeDialog.ShowAsync();
}
三个对话框按钮
ContentDialog 有三种不同类型的按钮可用于构建对话框体验。
- CloseButton - 必需 - 表示允许用户退出对话框的安全、无破坏性操作。 显示为最右侧的按钮。
- PrimaryButton - 可选 - 表示第一个“执行”操作。 显示为最左侧的按钮。
- SecondaryButton - 可选 - 表示第二个“执行”操作。 显示为中间的按钮。
使用内置按钮可相应放置按钮、确保按钮可正确响应键盘事件、确保在屏幕键盘启动时命令区域仍保持可见并使该对话框与其他对话框看起来一致。
CloseButton
每个对话框都应包含一个可使用户安心退出对话框的安全、无破坏性的操作按钮。
使用 ContentDialog.CloseButton API 可创建此按钮。 这样便可以为包括鼠标、键盘、触控和游戏板在内的所有输入创建适当的用户体验。 此体验将在以下情况下发生:
- 用户单击或点击 CloseButton。
- 用户按系统后退按钮。
- 用户按下键盘上的 ESC 按钮。
- 用户按 Gamepad B。
当用户单击对话框按钮时,ShowAsync 方法将返回 ContentDialogResult,告知用户单击哪个按钮。 按 CloseButton 返回 ContentDialogResult.None。
PrimaryButton 和 SecondaryButton
除了 CloseButton,还可以选择向用户提供与主要说明相关的一个或两个操作按钮。 将 PrimaryButton 用于第一个“执行”操作,将 SecondaryButton 用于第二个“执行”操作。 在三个按钮的对话框中,PrimaryButton 通常表示肯定的“执行”操作,而 SecondaryButton 通常表示中性或辅助“执行”操作。 例如,应用可能会提示用户订阅服务。 作为肯定“执行”操作的 PrimaryButton 将托管“订阅”文本,而作为中性“执行”操作的 SecondaryButton 将托管“尝试”文本。 CloseButton 允许用户取消,而不执行任何操作。
当用户单击 PrimaryButton 时,ShowAsync 方法将返回 ContentDialogResult.Primary。 当用户单击 SecondaryButton 时,ShowAsync 方法将返回 ContentDialogResult.Secondary。
DefaultButton
可以选择区分三个按钮之一,使其作为默认按钮。 指定默认按钮将导致发生以下情况:
- 该按钮接收“突出”按钮视觉处理
- 该按钮将自动响应 ENTER 键
- 当用户在键盘上按 ENTER 键时,与“默认”按钮关联的单击处理程序将激发,并且 ContentDialogResult 将返回与“默认”按钮关联的值
- 如果用户已将键盘焦点放在处理 ENTER 的控件上,默认按钮将不响应 ENTER 按下操作
- 打开对话框时,按钮会自动接收焦点,除非对话框内容包含可聚焦的 UI
使用 ContentDialog.DefaultButton 属性指示默认按钮。 默认情况下,不设置默认按钮。
private async void DisplaySubscribeDialog()
{
ContentDialog subscribeDialog = new ContentDialog
{
Title = "Subscribe to App Service?",
Content = "Listen, watch, and play in high definition for only $9.99/month. Free to try, cancel anytime.",
CloseButtonText = "Not Now",
PrimaryButtonText = "Subscribe",
SecondaryButtonText = "Try it",
DefaultButton = ContentDialogButton.Primary
};
ContentDialogResult result = await subscribeDialog.ShowAsync();
}
确认对话框 (确定/取消)
通过确认对话框,用户可以确认他们是否要执行操作。 他们可以确认操作,或选择取消。 典型的确认对话框有两个按钮:确认(“确定”)按钮和取消按钮。
-
一般情况下,确认按钮应位于左侧(主按钮),取消按钮(辅助按钮)应位于右侧。
- 如常规建议部分所述,使用带有文本的按钮来标识对主要指令或内容的特定响应。
某些平台将确认按钮放在右侧而不是左侧。 那么,为什么我们建议把它放在左边? 如果你假设大多数用户是右手的,他们用手拿着他们的手机,那么在左侧按下确认按钮实际上更舒服,因为该按钮更有可能位于用户的拇指弧内。屏幕右侧的按钮要求用户将拇指向内拉入不太舒适的位置。
AppWindow 或 Xaml 岛中的 ContentDialog
注意:本部分仅适用于面向 Windows 10 版本 1903 或更高版本的应用。 AppWindow 和 XAML 岛在早期的版本中不可用。 有关版本的详细信息,请参阅版本自适应应用。
默认情况下,内容对话框相对于根 ApplicationView 按模式显示。 使用 AppWindow 或 XAML 岛中的 ContentDialog 时,需要手动将对话框中的 XamlRoot 设置为 XAML 宿主的根。
为此,请将 ContentDialog 的 XamlRoot 属性设置为 AppWindow 或 XAML 岛中已包含的某个元素的同一 XamlRoot,如下所示。
private async void DisplayNoWifiDialog()
{
ContentDialog noWifiDialog = new ContentDialog
{
Title = "No wifi connection",
Content = "Check your connection and try again.",
CloseButtonText = "OK"
};
// Use this code to associate the dialog to the appropriate AppWindow by setting
// the dialog's XamlRoot to the same XamlRoot as an element that is already present in the AppWindow.
if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 8))
{
noWifiDialog.XamlRoot = elementAlreadyInMyAppWindow.XamlRoot;
}
ContentDialogResult result = await noWifiDialog.ShowAsync();
}
警告
每次只能在每个线程中打开一个 ContentDialog。 尝试打开两个 ContentDialog 会引发异常,即使尝试在独立的 AppWindow 中打开。
获取示例代码
- WinUI 库示例 - 以交互式格式查看所有 XAML 控件。