浮出控件Flyouts

浮出控件是可显示任意 UI 作为其内容的轻型消除容器。A flyout is a light dismiss container that can show arbitrary UI as its content. 浮出控件可能包含其他浮出控件或上下文菜单,用于创建嵌套体验。Flyouts can contain other flyouts or context menus to create a nested experience.

嵌套在浮出控件内的上下文菜单

获取 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: Flyout 类Platform APIs: Flyout class

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

  • 不要使用浮出控件替代工具提示上下文菜单Don't use a flyout instead of tooltip or context menu. 使用工具提示显示在指定时间后隐藏的简短描述。Use a tooltip to show a short description that hides after a specified time. 针对与 UI 元素相关的上下文操作(如复制和粘贴)使用上下文菜单。Use a context menu for contextual actions related to a UI element, such as copy and paste.

有关何时使用浮出控件以及何时使用对话框(类似控件)的建议,请参阅对话框和浮出控件For recommendations on when to use a flyout vs. when to use a dialog (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.

如何创建浮出控件How to create a flyout

浮出控件附加到特定控件。Flyouts are attached to specific controls. 可以使用 Placement 属性指定浮出控件显示的位置:顶部、左侧、底部、右侧或完整。You can use the Placement property to specify where a flyout appears: Top, Left, Bottom, Right, or Full. 如果你选择完整放置模式,应用将拉伸浮出控件,并使其在应用窗口中居中。If you select the Full placement mode, the app stretches the flyout and centers it inside the app window. 某些控件(如 Button)提供可用于关联浮出控件或上下文菜单Flyout 属性。Some controls, such as Button, provide a Flyout property that you can use to associate a flyout or context menu.

此示例创建一个在按下按钮时显示一些文本的简单浮出控件。This example creates a simple flyout that displays some text when the button is pressed.

<Button Content="Click me">
  <Button.Flyout>
     <Flyout>
        <TextBlock Text="This is a flyout!"/>
     </Flyout>
  </Button.Flyout>
</Button>

如果控件没有浮出控件属性,可以改用 FlyoutBase.AttachedFlyout 附加属性。If the control doesn't have a flyout property, you can use the FlyoutBase.AttachedFlyout attached property instead. 当你这样做时,还需要调用 FlyoutBase.ShowAttachedFlyout 方法来显示浮出控件。When you do this, you also need to call the FlyoutBase.ShowAttachedFlyout method to show the flyout.

此示例将一个简单的浮出控件添加到图像。This example adds a simple flyout to an image. 当用户点击该图像时,应用将显示该浮出控件。When the user taps the image, the app shows the flyout.

<Image Source="Assets/cliff.jpg" Width="50" Height="50"
  Margin="10" Tapped="Image_Tapped">
  <FlyoutBase.AttachedFlyout>
    <Flyout>
      <TextBlock Text="This is some text in a flyout."  />
    </Flyout>
  </FlyoutBase.AttachedFlyout>
</Image>
private void Image_Tapped(object sender, TappedRoutedEventArgs e)
{
    FlyoutBase.ShowAttachedFlyout((FrameworkElement)sender);
}

之前的示例已内联定义其浮出控件。The previous examples defined their flyouts inline. 你还可以定义一个浮出控件作为静态资源,然后将其用于多个元素。You can also define a flyout as a static resource and then use it with multiple elements. 此示例创建一个更复杂的浮出控件,可在点击其缩略图时显示图像的较大版本。This example creates a more complicated flyout that displays a larger version of an image when its thumbnail is tapped.

<!-- Declare the shared flyout as a resource. -->
<Page.Resources>
    <Flyout x:Key="ImagePreviewFlyout" Placement="Right">
        <!-- The flyout's DataContext must be the Image Source
             of the image the flyout is attached to. -->
        <Image Source="{Binding Path=Source}"
            MaxHeight="400" MaxWidth="400" Stretch="Uniform"/>
    </Flyout>
</Page.Resources>
<!-- Assign the flyout to each element that shares it. -->
<StackPanel>
    <Image Source="Assets/cliff.jpg" Width="50" Height="50"
           Margin="10" Tapped="Image_Tapped"
           FlyoutBase.AttachedFlyout="{StaticResource ImagePreviewFlyout}"
           DataContext="{Binding RelativeSource={RelativeSource Mode=Self}}"/>
    <Image Source="Assets/grapes.jpg" Width="50" Height="50"
           Margin="10" Tapped="Image_Tapped"
           FlyoutBase.AttachedFlyout="{StaticResource ImagePreviewFlyout}"
           DataContext="{Binding RelativeSource={RelativeSource Mode=Self}}"/>
    <Image Source="Assets/rainier.jpg" Width="50" Height="50"
           Margin="10" Tapped="Image_Tapped"
           FlyoutBase.AttachedFlyout="{StaticResource ImagePreviewFlyout}"
           DataContext="{Binding RelativeSource={RelativeSource Mode=Self}}"/>
</StackPanel>
private void Image_Tapped(object sender, TappedRoutedEventArgs e)
{
    FlyoutBase.ShowAttachedFlyout((FrameworkElement)sender);
}

设置浮出控件的样式Style a flyout

若要设置浮出控件的样式,请修改其 FlyoutPresenterStyleTo style a Flyout, modify its FlyoutPresenterStyle. 此示例显示一个环绕文本段落,并使屏幕阅读器可以访问该文本块。This example shows a paragraph of wrapping text and makes the text block accessible to a screen reader.

带有环绕文本的可访问浮出控件

<Flyout>
  <Flyout.FlyoutPresenterStyle>
    <Style TargetType="FlyoutPresenter">
      <Setter Property="ScrollViewer.HorizontalScrollMode"
          Value="Disabled"/>
      <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"/>
      <Setter Property="IsTabStop" Value="True"/>
      <Setter Property="TabNavigation" Value="Cycle"/>
    </Style>
  </Flyout.FlyoutPresenterStyle>
  <TextBlock Style="{StaticResource BodyTextBlockStyle}" Text="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."/>
</Flyout>

设置浮出控件样式,以实现 10 英尺体验Styling flyouts for 10-foot experiences

轻型消除控件(如浮出控件)会捕获瞬态 UI 内的键盘焦点和游戏板焦点,直到消除为止。Light dismiss controls like flyout trap keyboard and gamepad focus inside their transient UI until dismissed. 若要为此行为提供视觉提示,Xbox 上的轻型消除控件将绘制覆盖,以便使 UI 范围之外的对比度和可见性变暗。To provide a visual cue for this behavior, light dismiss controls on Xbox draw an overlay that dims the contrast and visibility of out of scope UI. 可以使用 LightDismissOverlayMode 属性修改此行为。This behavior can be modified with the LightDismissOverlayMode property. 默认情况下,浮出控件将在 Xbox(而非其他设备系列)上绘制轻型消除覆盖,不过应用可以选择强制使覆盖始终“打开”或始终“关闭” 。By default, flyouts will draw the light dismiss overlay on Xbox but not other device families, but apps can choose to force the overlay to be always On or always Off.

带有变暗覆盖的浮出控件

<MenuFlyout LightDismissOverlayMode="On">

轻型消除行为Light dismiss behavior

可通过快速的轻型消除操作来关闭浮出控件,这些操作包括Flyouts can be closed with a quick light dismiss action, including

  • 在浮出控件之外点击Tap outside the flyout
  • 按 Esc 键盘键Press the Escape keyboard key
  • 按硬件或软件系统后退按钮Press the hardware or software system Back button
  • 按游戏板 B 按钮Press the gamepad B button

通过点击消除时,此手势通常会被吸收,不会传递到下面的 UI。When dismissing with a tap, this gesture is typically absorbed and not passed on to the UI underneath. 例如,如果在开放式浮出控件后有一个按钮可见,则用户的第一次点击会消除浮出控件,但不会激活此按钮。For example, if there's a button visible behind an open flyout, the user's first tap dismisses the flyout but does not activate this button. 按下该按钮需要第二次点击。Pressing the button requires a second tap.

可通过将该按钮指定为浮出控件的输入直通元素来更改此行为。You can change this behavior by designating the button as an input pass-through element for the flyout. 浮出控件将因上述轻型消除操作而关闭,还会将点击事件传递给它的指定 OverlayInputPassThroughElementThe flyout will close as a result of the light dismiss actions described above and will also pass the tap event to its designated OverlayInputPassThroughElement. 请考虑采用此行为,以加快功能类似项目上的用户交互。Consider adopting this behavior to speed up user interactions on functionally similar items. 如果你的应用有收藏夹集合并且该集合中的每个项目都包括一个附加的浮出控件,用户可能希望快速连续地与多个浮出控件进行交互。If your app has a favorites collection and each item in the collection includes an attached flyout, it's reasonable to expect that users may want to interact with multiple flyouts in rapid succession.

[!NOTE] 请注意不要指定会导致破坏性操作的覆盖输入直通元素。Be careful not to designate an overlay input pass-through element which results in a destructive action. 用户已习惯谨慎执行不激活主要 UI 的轻型消除操作。Users have become habituated to discreet light dismiss actions which do not activate primary UI. 关闭、删除或相似的破坏性按钮不应激活轻型消除,以避免不期望的中断行为。Close, Delete or similarly destructive buttons should not activate on light dismiss to avoid unexpected and disruptive behavior.

在下面的示例中,将在第一次点击时激活 FavoritesBar 内的所有三个按钮。In the following example, all three buttons inside FavoritesBar will be activated on the first tap.

<Page>
    <Page.Resources>
        <Flyout x:Name="TravelFlyout" x:Key="TravelFlyout"
                OverlayInputPassThroughElement="{x:Bind FavoritesBar}">
            <StackPanel>
                <HyperlinkButton Content="Washington Trails Association"/>
                <HyperlinkButton Content="Washington Cascades - Go Northwest! A Travel Guide"/>
            </StackPanel>
        </Flyout>
    </Page.Resources>

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <StackPanel x:Name="FavoritesBar" Orientation="Horizontal">
            <HyperlinkButton x:Name="PageLinkBtn">Bing</HyperlinkButton>
            <Button x:Name="Folder1" Content="Travel" Flyout="{StaticResource TravelFlyout}"/>
            <Button x:Name="Folder2" Content="Entertainment" Click="Folder2_Click"/>
        </StackPanel>
        <ScrollViewer Grid.Row="1">
            <WebView x:Name="WebContent"/>
        </ScrollViewer>
    </Grid>
</Page>
private void Folder2_Click(object sender, RoutedEventArgs e)
{
     Flyout flyout = new Flyout();
     flyout.OverlayInputPassThroughElement = FavoritesBar;
     ...
     flyout.ShowAt(sender as FrameworkElement);
{

获取示例代码Get the sample code