Submenus

Um submenu é um contêiner de light dismiss que pode mostrar uma interface do usuário arbitrária como conteúdo. Os submenus podem conter outros submenus ou menus de contexto para criar uma experiência aninhada.

Esse é o controle correto?

  • Não use um submenu em vez de dica de ferramenta ou menu de contexto. Use uma dica de ferramenta para mostrar uma breve descrição que se oculta após um tempo especificado. Use um menu de contexto para ações contextuais relacionadas a um elemento da interface do usuário, como copiar e colar.

Para ver recomendações sobre quando usar um submenu e quando usar uma caixa de diálogo (um controle semelhante), confira Caixas de diálogo e submenus.

UWP e WinUI 2

Importante

As informações e exemplos neste artigo são otimizados para aplicativos que usam o SDK do Aplicativo Windows e o WinUI 3, mas geralmente são aplicáveis a aplicativos UWP que usam o WinUI 2. Consulte a referência de API da UWP para obter informações e exemplos específicos da plataforma.

Esta seção contém informações necessárias para usar o controle em um aplicativo UWP ou WinUI 2.

As APIs para esse controle existem no namespace Windows.UI.Xaml.Controls.

É recomendável usar a WinUI 2 mais recente para obter os estilos e modelos mais atuais para todos os controles. WinUI 2.2 ou posterior inclui um novo modelo para esse controle que usa cantos arredondados. Para obter mais informações, confira Raio de canto.

Criar um submenu

O aplicativo Galeria da WinUI 3 inclui exemplos interativos da maioria dos controles, recursos e funcionalidades da WinUI 3. Obtenha o aplicativo na Microsoft Store ou o código-fonte no GitHub

Os submenus são anexados a controles específicos. Você pode usar a propriedade Posicionamento para especificar onde um submenu aparece: Superior, Esquerda, Inferior, Direita ou Completo. Se você selecionar o modo de posicionamento completo, o aplicativo estenderá o submenu e o centralizará dentro da janela do aplicativo. Alguns controles, como Button, fornecem uma propriedade Flyout que você pode usar para associar a um submenu ou um menu de contexto.

Este exemplo cria um submenu simples que exibe algum texto quando o botão é pressionado.

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

Se o controle não tiver uma propriedade de submenu, você poderá usar a propriedade anexada FlyoutBase.AttachedFlyout . Ao fazer isso, você também precisa chamar o método FlyoutBase.ShowAttachedFlyout para mostrar o submenu.

Este exemplo adiciona um submenu simples a uma imagem. Quando o usuário toca na imagem, o aplicativo mostra o submenu.

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

Os exemplos anteriores definiram seus submenus embutidos. Você também pode definir um submenu como um recurso estático e usá-lo com vários elementos. Este exemplo cria um submenu mais complicado que exibe uma versão maior de uma imagem quando sua miniatura é tocada.

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

Estilizar um submenu

Para estilizar um submenu, modifique seu FlyoutPresenterStyle. Este exemplo mostra um parágrafo de quebra automática de texto e torna o bloco de texto acessível a um leitor de tela.

Submenu acessível com disposição de texto

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

Definição de estilo de submenus para a experiência de 3 metros

Faça o light dismiss dos controles, como teclado de interceptação de submenu e foco de gamepad na interface do usuário transitória, até serem ignorados. Para fornecer uma indicação visual desse comportamento, faça light dismiss dos controles no Xbox para desenhar uma sobreposição que esmaece o contraste e a visibilidade da interface do usuário fora do escopo. Esse comportamento pode ser modificado com a propriedade LightDismissOverlayMode. Por padrão, os submenus desenham a sobreposição de light dismiss no Xbox, mas não em outras famílias de dispositivos. No entanto, os aplicativos podem optar por forçar a sobreposição para estar sempre Ativada ou Desativada.

Submenu com sobreposição de esmaecimento

<MenuFlyout LightDismissOverlayMode="On">

Comportamento de light dismiss

Os submenus podem ser fechados com uma ação light dismiss rápida, incluindo

  • Tocar fora do submenu
  • Pressionar a tecla Escape no teclado
  • Pressionar o botão de Voltar do sistema de hardware ou software
  • Pressionar o botão B do gamepad

Ao ignorar com um toque, esse gesto é normalmente absorvido e não passado para a interface do usuário abaixo. Por exemplo, se houver um botão visível por trás de um submenu aberto, o primeiro toque do usuário fechará o submenu, mas não ativará esse botão. Pressionar o botão requer um segundo toque.

É possível alterar esse comportamento ao especificar o botão como um elemento de entrada de passagem para o submenu. O submenu fechará como resultado da ação de light dismiss descrita acima e passará o evento de toque para o OverlayInputPassThroughElement designado. Considere adotar esse comportamento para acelerar as interações do usuário em itens com funcionalidade semelhante. Se o aplicativo tem uma coleção de favoritos e cada item na coleção inclui um submenu anexado, é razoável esperar que os usuários queiram interagir com diversos submenus em sucessão rápida.

Observação

Tenha cuidado para não designar uma sobreposição de elemento de passagem de entrada que resulta em uma ação destrutiva. Os usuários se acostumaram às ações de light dismiss rápidas que não ativam a interface do usuário principal. Botões Fechar, Excluir ou destrutivos semelhantes não devem ser ativados em dispensas leves para evitar comportamentos inesperados e perturbadores.

No exemplo a seguir, todos os três botões dentro de FavoritesBar serão ativados no primeiro toque.

<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);
{

Obter o código de exemplo