对话框控件Dialog controls

对话框控件是用于提供上下文应用信息的模式 UI 覆盖。Dialog controls are modal UI overlays that provide contextual app information. 除非显式取消这些控件,否则它们会阻止与应用窗口的交互。They block interactions with the app window until being explicitly dismissed. 它们通常会请求用户进行某种类型的操作。They often request some kind of action from the user.

对话框示例

获取 Windows UI 库Get the Windows UI Library

WinUI 徽标

Windows UI 库 2.2 或更高版本包含此控件的使用圆角的新模板。Windows UI Library 2.2 or later includes a new template for this control that uses rounded corners. 有关详细信息,请参阅圆角半径For more info, see Corner radius. WinUI 是一种 NuGet 包,其中包含用于 Windows 应用的新控件和 UI 功能。WinUI is a NuGet package that contains new controls and UI features for Windows apps. 有关详细信息(包括安装说明),请参阅 Windows UI 库For more info, including installation instructions, see Windows UI Library.

平台 API: ContentDialog 类Platform APIs: ContentDialog class

这是正确的控件吗?Is this the right control?

使用对话框通知用户重要信息或在可以完成某个操作之前请求确认或其他信息。Use dialogs to notify users of important information or to request confirmation or additional info before an action can be completed.

有关何时使用对话框以及何时使用浮出控件(类似控件)的建议,请参阅对话框和浮出控件For recommendations on when to use a dialog vs. when to use a flyout (a similar control), see Dialogs and flyouts.

示例Examples

XAML 控件库XAML Controls Gallery
XAML controls gallery

如果已安装了 XAML 控件库应用,请单击此处打开该应用,了解 ContentDialogFlyout 的实际应用。If you have the XAML Controls Gallery app installed, click here to open the app and see the ContentDialog or Flyout in action.

一般指南General guidelines

  • 在对话框的第一行文本中清楚地标识问题或用户的目标。Clearly identify the issue or the user's objective in the first line of the dialog's text.
  • 对话框标题是主要说明并且是可选的。The dialog title is the main instruction and is optional.
    • 使用简短标题说明用户需要怎样处理对话框。Use a short title to explain what people need to do with the dialog.
    • 如果你使用对话框来传达简单的消息、错误或问题,则可以省略标题。If you're using the dialog to deliver a simple message, error or question, you can optionally omit the title. 可依赖内容文本来传达这样的核心信息。Rely on the content text to deliver that core information.
    • 确保标题与按钮选项直接相关。Make sure that the title relates directly to the button choices.
  • 对话框内容包含描述性文本,并且是必需的。The dialog content contains the descriptive text and is required.
    • 提供尽可能简单的消息、错误或阻止问题。Present the message, error, or blocking question as simply as possible.
    • 如果使用对话框标题,请使用内容区域提供更多详情或定义术语。If a dialog title is used, use the content area to provide more detail or define terminology. 不要只是修改几个措词来重复标题。Don't repeat the title with slightly different wording.
  • 必须至少显示一个对话框按钮。At least one dialog button must appear.
    • 确保你的对话框至少有一个按钮对应于安全、没有破坏性的操作,如“明白了!”、“关闭”或“取消”。Ensure that your dialog has at least one button corresponding to a safe, nondestructive action like "Got it!", "Close", or "Cancel". 使用 CloseButton API 可添加该按钮。Use the CloseButton API to add this button.
    • 使用主要说明或内容的特定响应作为按钮文本。Use specific responses to the main instruction or content as button text. 例如,“你是否希望允许 AppName 访问你的位置”,后跟“允许”和“拒绝”按钮。An example is, "Do you want to allow AppName to access your location?", followed by "Allow" and "Block" buttons. 具体的响应可以使用户更快速的理解,以便进行高效的决策。Specific responses can be understood more quickly, resulting in efficient decision making.
    • 确保操作按钮的文本保持简明。Ensure that the text of the action buttons is concise. 简短的字符串使用户能够快速、自信地做出选择。Short strings enable the user to make a choice quickly and confidently.
    • 除了安全、无破坏性的操作外,你还可以选择为用户提供一个或两个与主要说明相关的操作按钮。In addition to the safe, nondestructive action, you may optionally present the user with one or two action buttons related to the main instruction. 这些“执行”操作按钮用于确认对话框的重点。These "do it" action buttons confirm the main point of the dialog. 使用 PrimaryButton 和 SecondaryButton API 可添加这些“执行”操作。Use the PrimaryButton and SecondaryButton APIs to add these "do it" actions.
    • “执行”操作按钮应显示为最左侧按钮。The "do it" action button(s) should appear as the leftmost buttons. 安全、无破坏性的操作应显示为最右侧的按钮。The safe, nondestructive action should appear as the rightmost button.
    • 可以选择三个按钮之一作为对话框的默认按钮。You may optionally choose to differentiate one of the three buttons as the dialog's default button. 使用 DefaultButton API 可区分其中一个按钮。Use the DefaultButton API to differentiate one of the buttons.
  • 不要为与页面上的特定位置具有上下文关系的错误(例如,密码字段等位置的验证错误)使用对话框,请使用应用的画布本身显示内联错误。Don't use dialogs for errors that are contextual to a specific place on the page, such as validation errors (in password fields, for example), use the app's canvas itself to show inline errors.
  • 使用 ContentDialog 类生成对话框体验。Use the ContentDialog class to build your dialog experience. 不要使用已弃用的 MessageDialog API。Don't use the deprecated MessageDialog API.

如何创建对话框How to create a dialog

若要创建对话框,你使用 ContentDialog 类To create a dialog, you use the ContentDialog class. 你可以使用代码或标记创建对话框。You can create a dialog in code or markup. 尽管使用 XAML 定义 UI 元素通常更容易,但对于简单对话框,实际上只使用代码更容易。Although its usually easier to define UI elements in XAML, in the case of a simple dialog, it's actually easier to just use code. 此示例创建一个对话框来通知用户没有 WiFi 连接,然后使用 ShowAsync 方法显示它。This example creates a dialog to notify the user that there's no WiFi connection, and then uses the ShowAsync method to display it.

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 来通知你用户单击了哪个按钮。When the user clicks a dialog button, the ShowAsync method returns a ContentDialogResult to let you know which button the user clicks.

此示例中的对话框提出一个问题,并使用返回的 ContentDialogResult 确定用户的响应。The dialog in this example asks a question and uses the returned ContentDialogResult to determine the user's response.

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.
    }
}

提供安全操作Provide a safe action

由于对话框会阻止用户交互,而且按钮是用户消除对话框的主要机制,因此请确保你的对话框至少包含一个“安全”且无破坏性的按钮,如“关闭”或“明白!”。Because dialogs block user interaction, and because buttons are the primary mechanism for users to dismiss the dialog, ensure that your dialog contains at least one "safe" and nondestructive button such as "Close" or "Got it!". 所有对话应都至少应包含一个安全操作按钮来关闭对话框。All dialogs should contain at least one safe action button to close the dialog. 这可以确保用户能自信地关闭对话框,而未执行操作。This ensures that the user can confidently close the dialog without performing an action.
一个按钮对话框An one button dialog

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();
}

当对话框用于显示阻止问题时,你的对话框应向用户显示与该问题相关的操作按钮。When dialogs are used to display a blocking question, your dialog should present the user with action buttons related to the question. 这个“安全”且无破坏性的按钮可能会伴随一个或两个“执行”操作按钮。The "safe" and nondestructive button may be accompanied by one or two "do it" action buttons. 在向用户提供多个选项时,请确保按钮可清晰地说明与所提出问题相关的“执行”和安全的“不执行”操作。When presenting the user with multiple options, ensure that the buttons clearly explain the "do it" and safe/"don't do it" actions related to the question proposed.

两个按钮对话框

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();
}

向用户提供两个“执行”操作和一个“不执行”操作时,可以使用三个按钮对话框。Three button dialogs are used when you present the user with two "do it" actions and a "don't do it" action. 应慎用三个按钮对话框,辅助操作与安全/关闭操作之间应有清晰的区别。Three button dialogs should be used sparingly with clear distinctions between the secondary action and the safe/close action.

包含三个按钮的对话框

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();
}

三个对话框按钮The three dialog buttons

ContentDialog 有三种不同类型的按钮可用于构建对话框体验。ContentDialog has three different types of buttons that you can use to build a dialog experience.

  • CloseButton - 必需 - 表示允许用户退出对话框的安全、无破坏性操作。CloseButton - Required - Represents the safe, nondestructive action that enables the user to exit the dialog. 显示为最右侧的按钮。Appears as the rightmost button.
  • PrimaryButton - 可选 - 表示第一个“执行”操作。PrimaryButton - Optional - Represents the first "do it" action. 显示为最左侧的按钮。Appears as the leftmost button.
  • SecondaryButton - 可选 - 表示第二个“执行”操作。SecondaryButton - Optional - Represents the second "do it" action. 显示为中间的按钮。Appears as the middle button.

使用内置按钮可相应放置按钮、确保按钮可正确响应键盘事件、确保在屏幕键盘启动时命令区域仍保持可见并使该对话框与其他对话框看起来一致。Using the built-in buttons will position the buttons appropriately, ensure that they correctly respond to keyboard events, ensure that the command area remains visible even when the on-screen keyboard is up, and will make the dialog look consistent with other dialogs.

CloseButtonCloseButton

每个对话框都应包含一个可使用户安心退出对话框的安全、无破坏性的操作按钮。Every dialog should contain a safe, nondestructive action button that enables the user to confidently exit the dialog.

使用 ContentDialog.CloseButton API 可创建此按钮。Use the ContentDialog.CloseButton API to create this button. 这样便可以为包括鼠标、键盘、触控和游戏板在内的所有输入创建适当的用户体验。This allows you to create the right user experience for all inputs including mouse, keyboard, touch, and gamepad. 此体验将在以下情况下发生:This experience will happen when:

  1. 用户单击或点击关闭按钮The user clicks or taps on the CloseButton
  2. 用户按下系统后退按钮The user presses the system back button
  3. 用户按下键盘上的 ESC 按钮The user presses the ESC button on the keyboard
  4. 用户按下游戏板 BThe user presses Gamepad B

当用户单击某个对话框按钮时,ShowAsync 方法返回一个 ContentDialogResult 来通知你用户单击了哪个按钮。When the user clicks a dialog button, the ShowAsync method returns a ContentDialogResult to let you know which button the user clicks. 按 CloseButton 返回 ContentDialogResult.None。Pressing on the CloseButton returns ContentDialogResult.None.

PrimaryButton 和 SecondaryButtonPrimaryButton and SecondaryButton

除了 CloseButton,还可以选择向用户提供与主要说明相关的一个或两个操作按钮。In addition to the CloseButton, you may optionally present the user with one or two action buttons related to the main instruction. 将 PrimaryButton 用于第一个“执行”操作,将 SecondaryButton 用于第二个“执行”操作。Leverage PrimaryButton for the first "do it" action, and SecondaryButton for the second "do it" action. 在三个按钮的对话框中,PrimaryButton 通常表示肯定的“执行”操作,而 SecondaryButton 通常表示中性或辅助“执行”操作。In three-button dialogs, the PrimaryButton generally represents the affirmative "do it" action, while the SecondaryButton generally represents a neutral or secondary "do it" action. 例如,应用可能会提示用户订阅服务。For example, an app may prompt the user to subscribe to a service. 作为肯定“执行”操作的 PrimaryButton 将托管“订阅”文本,而作为中性“执行”操作的 SecondaryButton 将托管“尝试”文本。The PrimaryButton as the affirmative "do it" action would host the Subscribe text, while the SecondaryButton as the neutral "do it" action would host the Try it text. CloseButton 允许用户取消,而不执行任何操作。The CloseButton would allow the user to cancel without performing either action.

当用户单击 PrimaryButton 时,ShowAsync 方法将返回 ContentDialogResult.Primary。When the user clicks on the PrimaryButton, the ShowAsync method returns ContentDialogResult.Primary. 当用户单击 SecondaryButton 时,ShowAsync 方法将返回 ContentDialogResult.Secondary。When the user clicks on the SecondaryButton, the ShowAsync method returns ContentDialogResult.Secondary.

包含三个按钮的对话框

DefaultButtonDefaultButton

可以选择区分三个按钮之一,使其作为默认按钮。You may optionally choose to differentiate one of the three buttons as the default button. 指定默认按钮将导致发生以下情况:Specifying the default button causes the following to happen:

  • 该按钮接收“突出”按钮视觉处理The button receives the Accent Button visual treatment
  • 该按钮将自动响应 ENTER 键The button will respond to the ENTER key automatically
    • 当用户在键盘上按 ENTER 键时,与“默认”按钮关联的单击处理程序将激发,并且 ContentDialogResult 将返回与“默认”按钮关联的值When the user presses the ENTER key on the keyboard, the click handler associated with the Default Button will fire and the ContentDialogResult will return the value associated with the Default Button
    • 如果用户已将键盘焦点放在处理 ENTER 的控件上,默认按钮将不响应 ENTER 按下操作If the user has placed Keyboard Focus on a control that handles ENTER, the Default Button will not respond to ENTER presses
  • 打开对话框时,按钮会自动接收焦点,除非对话框内容包含可聚焦的 UIThe button will receive focus automatically when the Dialog is opened unless the dialog's content contains focusable UI

使用 ContentDialog.DefaultButton 属性指示默认按钮。Use the ContentDialog.DefaultButton property to indicate the default button. 默认情况下,不设置默认按钮。By default, no default button is set.

具有默认按钮的三个按钮对话框

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();
}

确认对话框(确定/取消)Confirmation dialogs (OK/Cancel)

通过确认对话框,用户可以确认他们是否要执行操作。A confirmation dialog gives users the chance to confirm that they want to perform an action. 他们可以确认操作,也可以选择取消。They can affirm the action, or choose to cancel. 典型的确认对话框有两个按钮:一个确认(“确定”)按钮和一个取消按钮。A typical confirmation dialog has two buttons: an affirmation ("OK") button and a cancel button.

  • 一般情况下,确认按钮(主要按钮)应位于左侧,取消按钮(辅助按钮)应位于右侧。In general, the affirmation button should be on the left (the primary button) and the cancel button (the secondary button) should be on the right.

    An OK/cancel dialog
  • 如一般建议部分中所述,使用带有文本的按钮,该文本可标识特定于主要说明或内容的响应。As noted in the general recommendations section, use buttons with text that identifies specific responses to the main instruction or content.

某些平台将确认按钮放置在右侧,而不是左侧。Some platforms put the affirmation button on the right instead of the left. 那么,为什么我们建议将它放在左侧呢?So why do we recommend putting it on the left? 如果你假设大多数用户惯用右手并且他们用右手拿着手机,按位于左侧的确认按钮实际上更为舒适,因为该按钮更有可能处于用户的拇指弧范围内。位于屏幕右侧的按钮需要用户将拇指向内收缩到不太舒适的位置。If you assume that the majority of users are right-handed and they hold their phone with that hand, it's actually more comfortable to press the affirmation button when it's on the left, because the button is more likely to be within the user's thumb-arc. Buttons on the right-side of the screen require the user to pull their thumb inward into a less-comfortable position.

AppWindow 或 Xaml 岛中的 ContentDialogContentDialog in AppWindow or Xaml Islands

注意:本部分仅适用于面向 Windows 10 版本 1903 或更高版本的应用。NOTE: This section applies only to apps that target Windows 10, version 1903 or later. AppWindow 和 XAML 岛在早期的版本中不可用。AppWindow and XAML Islands are not available in earlier versions. 有关版本的详细信息,请参阅版本自适应应用For more info about versioning, see Version adaptive apps.

默认情况下,内容对话框相对于根 ApplicationView 按模式显示。By default, content dialogs display modally relative to the root ApplicationView. 使用 AppWindowXAML 岛中的 ContentDialog 时,需要手动将对话框中的 XamlRoot 设置为 XAML 宿主的根。When you use ContentDialog inside of either an AppWindow or a XAML Island, you need to manually set the XamlRoot on the dialog to the root of the XAML host.

为此,请将 ContentDialog 的 XamlRoot 属性设置为 AppWindow 或 XAML 岛中已包含的某个元素的同一 XamlRoot,如下所示。To do so, set the ContentDialog's XamlRoot property to the same XamlRoot as an element already in the AppWindow or XAML Island, as shown here.

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。There can only be one ContentDialog open per thread at a time. 尝试打开两个 ContentDialog 会引发异常,即使尝试在独立的 AppWindow 中打开。Attempting to open two ContentDialogs will throw an exception, even if they are attempting to open in separate AppWindows.

获取示例代码Get the sample code