Popup

Un elemento emergente muestra el contenido encima de la otra interfaz de usuario de la aplicación. La clase Popup en el espacio de nombres Microsoft.UI.Xaml.Controls.Primitives es un contenedor de uso general para ese contenido. No tiene ninguna plantilla visual predeterminada, por lo que proporcionas el contenido, su apariencia y la lógica que lo abre y lo cierra.

Popup es un componente básico de bajo nivel. WinUI también proporciona controles para los tipos comunes de interfaz de usuario transitoria, como submenús flotantes, cuadros de diálogo, sugerencias para enseñanza e información sobre herramientas. Estos controles incluyen su propio estilo, ubicación y comportamiento de descarte.

Un botón con la etiqueta

¿Es este el control adecuado?

No utilice un Popup si un control de nivel superior se ajusta a su escenario. Utilice estos controles en su lugar:

Scenario Control
Muestra información o recopila entradas relacionadas con un elemento, en una interfaz de usuario que se cierra cuando el usuario hace clic fuera de ella. Submenú flotante
Mostrar una lista de comandos o opciones. MenuFlyout
Haga una pregunta o muestre información a la que el usuario debe responder antes de continuar. ContentDialog
Señala una característica nueva o importante, con o sin establecer como objetivo un elemento específico. TeachingTip
Muestra una breve descripción de un elemento cuando el usuario mantiene el puntero sobre él o mueve el foco a él. Tooltip

Use un Popup cuando necesite contenido personalizado que flote por encima de su interfaz de usuario y ninguno de estos controles satisfaga sus necesidades. Por ejemplo, puede usar un elemento emergente como superposición a la que usted mismo da estilo y posiciona.

Un elemento emergente no es modal, por lo que el usuario todavía puede interactuar con la interfaz de usuario detrás de ella. Si el usuario debe responder antes de continuar, use contentDialog.

Recommendations

  • Asigne al contenido emergente un fondo, un borde y esquinas redondeadas para que destaque de la interfaz de usuario detrás de él. El ejemplo de la Galería de WinUI 3 usa los recursos AcrylicBackgroundFillColorDefaultBrush, SurfaceStrokeColorDefaultBrush y OverlayCornerRadius. Para obtener más información, consulta material Acrylic y ThemeShadow en Popups.
  • Si no habilita el cierre al hacer clic fuera, incluya un botón u otro control que cierre el elemento emergente.
  • Mantenga el contenido emergente breve y céntrese en una sola tarea.

Crear una ventana emergente

Icono de la galería de WinUI 3 La aplicación Galería de WinUI 3 incluye ejemplos interactivos de características y controles winUI. Obtenga la aplicación desde el Microsoft Store o busque el código fuente en GitHub.

Un elemento emergente aloja un único elemento, que establece como su Elemento secundario. El elemento secundario suele ser un panel o un UserControl que define el contenido del elemento emergente. Para mostrar el elemento emergente, establezca IsOpen en true. Para ocultarlo, establezca IsOpen en false.

Este ejemplo se basa en el ejemplo de la galería de WinUI 3. Declara un elemento emergente junto al botón que lo abre y el contenido emergente incluye un botón que cierra el elemento emergente.

<Grid HorizontalAlignment="Left" VerticalAlignment="Top">
    <Button Content="Show popup" Click="ShowPopupClicked" />
    <Popup x:Name="StandardPopup" HorizontalOffset="200" VerticalOffset="0">
        <Grid MinWidth="240"
              Padding="16"
              Background="{ThemeResource AcrylicBackgroundFillColorDefaultBrush}"
              BorderBrush="{ThemeResource SurfaceStrokeColorDefaultBrush}"
              BorderThickness="1"
              CornerRadius="{StaticResource OverlayCornerRadius}">
            <StackPanel Spacing="8">
                <TextBlock FontSize="16" Text="Simple popup" />
                <Button Content="Close" Click="ClosePopupClicked" />
            </StackPanel>
        </Grid>
    </Popup>
</Grid>
// Opens the popup if it isn't already open.
private void ShowPopupClicked(object sender, RoutedEventArgs e)
{
    if (!StandardPopup.IsOpen)
    {
        StandardPopup.IsOpen = true;
    }
}

// Closes the popup when the user clicks the Close button inside it.
private void ClosePopupClicked(object sender, RoutedEventArgs e)
{
    if (StandardPopup.IsOpen)
    {
        StandardPopup.IsOpen = false;
    }
}

Crear un elemento emergente en el código

También puede crear un elemento emergente en el código sin agregarlo al árbol visual. Un elemento emergente que declare en XAML, o agregue a un panel en el árbol visual, obtiene su XamlRoot de su elemento primario. Un elemento emergente que no tenga primario no, por lo que debe establecer su propiedad XamlRoot antes de abrirlo.

private Popup? _popup;

private void ShowPopupFromCodeClicked(object sender, RoutedEventArgs e)
{
    _popup ??= new Popup
    {
        // PopupContent is a UserControl in your app that defines the popup content.
        Child = new PopupContent(),
        IsLightDismissEnabled = true,

        // Required because this popup isn't in the visual tree. Use the XamlRoot
        // of an element that's already loaded, such as the button that was clicked.
        XamlRoot = ((UIElement)sender).XamlRoot
    };

    _popup.IsOpen = true;
}

Importante

En WinUI 3, abrir un elemento emergente que no tenga ni elemento primario ni XamlRoot genera un error. El null de un elemento es XamlRoot hasta que el elemento se agrega al árbol visual activo, por lo que obtén el valor de un elemento que ya está cargado, en lugar de en un constructor de página. En una Window clase, puede usar this.Content.XamlRoot. Para obtener más información, consulta ContentDialog y Popup.

Note

Un elemento emergente que no está en el árbol visual no se cambia de posición cuando aparece el teclado táctil, por lo que el teclado puede cubrirlo. Si el elemento emergente contiene controles de entrada de texto, como un TextBox, declare el elemento emergente en XAML o agréguelo a un panel del árbol visual.

Cerrar un elemento emergente con descarte ligero

De forma predeterminada, un elemento emergente permanece abierto hasta que el código establece IsOpen en false. Establezca IsLightDismissEnabled en true para cerrar el elemento emergente cuando el usuario hace clic o pulsa fuera de él, o presiona la tecla Esc. Este comportamiento se llama descarte ligero.

De forma predeterminada, el área fuera de una ventana emergente de cierre al hacer clic fuera no se oscurece. Para oscurecerlo, establezca LightDismissOverlayMode en On. Esta propiedad no tiene ningún efecto cuando IsLightDismissEnabled es false.

<Popup x:Name="LightDismissPopup"
       IsLightDismissEnabled="True"
       LightDismissOverlayMode="On">
    <Border Padding="16"
            Background="{ThemeResource AcrylicBackgroundFillColorDefaultBrush}"
            BorderBrush="{ThemeResource SurfaceStrokeColorDefaultBrush}"
            BorderThickness="1"
            CornerRadius="{StaticResource OverlayCornerRadius}">
        <TextBlock Text="Click outside this popup or press Esc to close it." />
    </Border>
</Popup>

Posicionar un elemento emergente

Puede colocar un elemento emergente mediante desplazamientos o en relación con otro elemento.

Usar desplazamientos

HorizontalOffset y VerticalOffset establecen la posición del elemento emergente, en píxeles. El punto del que se miden los desplazamientos depende de si el elemento emergente tiene un elemento primario:

  • Un elemento emergente en el árbol visual tiene un desplazamiento respecto a su propia posición en el diseño de su elemento primario. Por ejemplo, en una vertical StackPanel, esa posición está debajo de los elementos que vienen antes del elemento emergente. En el primer ejemplo, el elemento emergente comparte una sola celda Grid con el botón, por lo que aparece 200 píxeles a la derecha de la esquina superior izquierda de la Grid.
  • Un elemento emergente que no tiene ningún elemento primario o padre, como el que creas en el código, se desplaza desde la esquina superior izquierda de su raíz XAML, que suele ser el área de contenido de la ventana de la aplicación.

Coloca una ventana emergente junto a un elemento

Para mostrar un elemento emergente junto a un elemento específico, establezca PlacementTarget en ese elemento. A continuación, establezca DesiredPlacement en un valor popupPlacementMode distinto de Auto, como Bottom o RightEdgeAlignedTop.

Cuando se abre el elemento emergente, el marco lo coloca en relación con el elemento de destino. Si el elemento emergente no encaja en la posición preferida, el framework lo mueve al lado opuesto del elemento de destino. HorizontalOffset y VerticalOffset se siguen aplicando y desplazan el elemento emergente desde la posición calculada.

ActualPlacement notifica dónde se muestra el elemento emergente. El evento ActualPlacementChanged se produce cuando ese valor cambia mientras el elemento emergente está abierto.

<StackPanel Spacing="8">
    <Button x:Name="DetailsButton" Content="Show details" Click="ShowDetailsClicked" />
    <TextBlock x:Name="PlacementStatus" />
    <Popup x:Name="DetailsPopup"
           PlacementTarget="{x:Bind DetailsButton}"
           DesiredPlacement="BottomEdgeAlignedLeft"
           IsLightDismissEnabled="True"
           ActualPlacementChanged="DetailsPopup_ActualPlacementChanged">
        <Border Padding="16"
                Background="{ThemeResource AcrylicBackgroundFillColorDefaultBrush}"
                BorderBrush="{ThemeResource SurfaceStrokeColorDefaultBrush}"
                BorderThickness="1"
                CornerRadius="{StaticResource OverlayCornerRadius}">
            <TextBlock Text="This popup appears below the button when there's room." />
        </Border>
    </Popup>
</StackPanel>
private void ShowDetailsClicked(object sender, RoutedEventArgs e)
{
    DetailsPopup.IsOpen = true;
}

private void DetailsPopup_ActualPlacementChanged(object sender, object e)
{
    // ActualPlacement differs from DesiredPlacement when the popup
    // doesn't fit in the preferred position.
    PlacementStatus.Text = $"Actual placement: {DetailsPopup.ActualPlacement}";
}

Mostrar un elemento emergente fuera de la ventana de la aplicación

De forma predeterminada, un elemento emergente está restringido a los límites de su raíz XAML, que suele ser el área de contenido de la ventana de la aplicación. A partir de SDK de Aplicaciones para Windows 1.4, puede establecer ShouldConstrainToRootBounds en false para permitir que el elemento emergente se extienda más allá de la ventana. Por ejemplo, puede hacerlo cuando el elemento emergente es más grande que una ventana pequeña.

Establezca ShouldConstrainToRootBounds antes de abrir la ventana emergente por primera vez. No se puede cambiar después de que se haya abierto el elemento emergente.

<Popup x:Name="UnconstrainedPopup" ShouldConstrainToRootBounds="False">
    <!-- Popup content -->
</Popup>

Animar una ventana emergente

Para animar el contenido emergente cuando aparezca, agregue una transición a la colección ChildTransitions . PopupThemeTransition proporciona la animación para la interfaz de usuario emergente, como el contenido similar a un tooltip, tal como aparece.

<Popup x:Name="AnimatedPopup" IsLightDismissEnabled="True">
    <Popup.ChildTransitions>
        <TransitionCollection>
            <PopupThemeTransition />
        </TransitionCollection>
    </Popup.ChildTransitions>
    <Border Padding="16"
            Background="{ThemeResource AcrylicBackgroundFillColorDefaultBrush}"
            BorderBrush="{ThemeResource SurfaceStrokeColorDefaultBrush}"
            BorderThickness="1"
            CornerRadius="{StaticResource OverlayCornerRadius}">
        <TextBlock Text="This content animates when the popup opens." />
    </Border>
</Popup>

Para controlar las animaciones de mostrar y ocultar desde un guion gráfico en su lugar, use PopInThemeAnimation y PopOutThemeAnimation. Para obtener más información, consulte Mostrar u ocultar elemento emergente.

Responder cuando se abra o se cierre una ventana emergente

El evento Opened se produce cuando IsOpen se establece en true. El evento Cerrado se produce cuando IsOpen se establece en false, incluso cuando el elemento emergente se cierra mediante descarte ligero. Usa Closed para tareas que deban realizarse independientemente de cómo se cierre la ventana emergente. Por ejemplo, el ejemplo de WinUI 3 Gallery usa Closed para volver a habilitar una configuración que deshabilita mientras el elemento emergente está abierto.

Ambos eventos usan EventHandler<object>, por lo que sus controladores toman un remitente object y un argumento de evento object.

<StackPanel Spacing="8">
    <TextBlock x:Name="StatusText" />
    <Popup x:Name="StatusPopup"
           IsLightDismissEnabled="True"
           Opened="StatusPopup_Opened"
           Closed="StatusPopup_Closed">
        <!-- Popup content -->
    </Popup>
</StackPanel>
private void StatusPopup_Opened(object sender, object e)
{
    StatusText.Text = "The popup is open.";
}

private void StatusPopup_Closed(object sender, object e)
{
    // Closed occurs for every close, including light dismiss.
    StatusText.Text = "The popup is closed.";
}

Teclado, foco y accesibilidad

  • Cuando se habilita el descarte ligero, abrir el elemento emergente mueve el foco a él y cerrarlo devuelve el foco al elemento que tenía el foco antes. El usuario también puede presionar Esc para cerrar el elemento emergente.
  • Cuando light dismiss no está habilitado, el elemento emergente no mueve el foco cuando se abre. Mueva el foco a un elemento del elemento emergente después de abrirlo, incluya un botón Cerrar al que los usuarios del teclado puedan acceder y devuelva el foco al elemento que abrió el elemento emergente después de cerrarlo.
  • Un elemento emergente no genera eventos enrutados, como KeyDown y PointerPressed. Para controlar estos eventos, asocie los controladores al elemento secundario del elemento emergente en su lugar.
  • Asegúrese de que cada elemento interactivo del elemento emergente tenga un nombre accesible. Para obtener más información, consulta Accesibilidad del teclado y Exponer información de accesibilidad básica.