Mostrar vários modos de exibição para um aplicativo

Wireframe mostrando um aplicativo com várias janelas

Ajude os usuários a serem mais produtivos permitindo que eles exibam partes independentes do aplicativo em janelas separadas. Quando você cria várias janelas para um aplicativo, a barra de tarefas mostra cada janela separadamente. Os usuários podem mover, redimensionar, mostrar e ocultar janelas do aplicativo de maneira independente e alternar janelas do aplicativo como se elas fossem aplicativos separados.

APIs importantes: namespace Windows.UI.ViewManagement, namespace Windows.UI.WindowManagement

Quando um aplicativo deve usar várias exibições?

Há diversos cenários que podem se beneficiar do uso de várias exibições. Veja aqui alguns exemplos:

  • Um aplicativo de email que permite aos usuários exibir uma lista de mensagens recebidas ao redigir um novo email
  • Um aplicativo de catálogo de endereços que permite aos usuários comparar as informações de contato de várias pessoas lado a lado
  • Um player de música que permite aos usuários ver o que está sendo reproduzido durante a navegação em uma lista de outras músicas disponíveis
  • Um aplicativo de anotações que permite aos usuários copiar informações de uma página de anotações para outra
  • Um aplicativo de leitura que permite aos usuários abrir vários artigos para leitura posterior, após a oportunidade de ver todos os títulos principais

Embora cada layout de aplicativo seja exclusivo, recomendamos incluir um botão de "nova janela" em um local previsível, como o canto superior direito do conteúdo que pode ser aberto em uma nova janela. Considere também incluir uma opção de menu de contexto em "Abrir em uma nova janela".

Para criar instâncias separadas do seu aplicativo (em vez de janelas separadas para a mesma instância), confira Criar um aplicativo do Windows de várias instâncias.

Hosts de janelas

Há diferentes formas de hospedar conteúdo do Windows em um aplicativo.

  • CoreWindow/ApplicationView

    Modo de exibição do aplicativo é o emparelhamento 1:1 de um thread e uma janela que o aplicativo usa para exibir conteúdo. O primeiro modo de exibição criado quando o aplicativo é iniciado é chamado de modo de exibição principal. Cada CoreWindow/ApplicationView opera em seu próprio thread. Ter que trabalhar em diferentes threads da interface do usuário pode complicar aplicativos com várias janelas.

    A exibição principal do seu aplicativo é sempre hospedada em um ApplicationView. O conteúdo em uma janela secundária pode ser hospedado em um ApplicationView ou em um AppWindow.

    Para saber como usar o ApplicationView para mostrar janelas secundárias no seu aplicativo, confira Use ApplicationView.

  • AppWindow

    O AppWindow simplifica a criação de aplicativos do Windows com várias janelas porque opera no mesmo thread da IU do qual ele foi criado.

    A classe AppWindow e outras APIs no namespace WindowManagement estão disponíveis a partir do Windows 10, versão 1903 (SDK 18362). Caso seu aplicativo tenha como alvo versões anteriores do Windows 10, use o ApplicationView para criar janelas secundárias.

    Para saber como usar o AppWindow para mostrar janelas secundárias no seu aplicativo, confira Use AppWindow.

    Observação

    AppWindow está atualmente em versão prévia. Isso significa que você pode enviar aplicativos que usam o AppWindow à Store, mas alguns componentes de plataforma e estrutura são conhecidos por não funcionar com o AppWindow (confira Limitações).

  • DesktopWindowXamlSource (Ilhas XAML)

    O conteúdo de XAML UWP em um aplicativo Win32 (usando HWND), também conhecido como Ilhas XAML, é hospedado em um DesktopWindowXamlSource.

    Para saber mais sobre Ilhas XAML, confira Usar a API de hospedagem de XAML UWP em um aplicativo da área de trabalho

Viabilizar a portabilidade de código em hosts de janelas

Quando o conteúdo XAML é exibido em um CoreWindow, sempre há um ApplicationView e uma Janela XAML associados. Você pode usar APIs nessas classes para obter informações como os limites de janela. Para recuperar uma instância dessas classes, use o método estático CoreWindow.GetForCurrentThread, o método ApplicationView.GetForCurrentView ou a propriedade Window.Current. Além disso, há muitas classes que usam o padrão de GetForCurrentView para recuperar uma instância da classe, como DisplayInformation.GetForCurrentView.

Essas APIs funcionam porque há apenas uma árvore de conteúdo XAML para um CoreWindow/ApplicationView, portanto, o XAML sabe que o contexto no qual ele está hospedado é o CoreWindow/ApplicationView.

Quando o conteúdo XAML está em execução dentro de um AppWindow ou DesktopWindowXamlSource, você pode ter várias árvores de conteúdo XAML em execução no mesmo thread ao mesmo tempo. Nesse caso, essas APIs não fornecem as informações corretas, já que o conteúdo não é mais executado dentro do CoreWindow/ApplicationView atual (e da Janela XAML).

Para garantir que seu código funcione corretamente em todos os hosts de janelas, você deve substituir as APIs que dependem de CoreWindow, ApplicationView e Window por novas APIs que obtêm o contexto da classe XamlRoot. A classe XamlRoot representa uma árvore de conteúdo XAML e informações sobre o contexto no qual ele está hospedado, seja um CoreWindow, AppWindow ou DesktopWindowXamlSource. Essa camada de abstração permite que você escreva o mesmo código independentemente do host de janelas em que o XAML é executado.

Esta tabela mostra o código que não funciona corretamente em hosts de janelas e o novo código portátil pelo qual você pode substituí-lo, bem como algumas APIs que você não precisa alterar.

Se você usou... Substitua por...
CoreWindow.GetForCurrentThread().Bounds uiElement.XamlRoot.Size
CoreWindow.GetForCurrentThread().SizeChanged uiElement.XamlRoot.Changed
CoreWindow.Visible uiElement.XamlRoot.IsHostVisible
CoreWindow.VisibilityChanged uiElement.XamlRoot.Changed
CoreWindow.GetForCurrentThread().GetKeyState Inalterado. Isso tem suporte no AppWindow e no DesktopWindowXamlSource.
CoreWindow.GetForCurrentThread().GetAsyncKeyState Inalterado. Isso tem suporte no AppWindow e no DesktopWindowXamlSource.
Window.Current Retorna o principal objeto da Janela XAML associado ao CoreWindow atual. Confira a Observação após esta tabela.
Window.Current.Bounds uiElement.XamlRoot.Size
Window.Current.Content Raiz UIElement = uiElement. XamlRoot. Conteúdo
Window.Current.Compositor Inalterado. Isso tem suporte no AppWindow e no DesktopWindowXamlSource.
VisualTreeHelper.FindElementsInHostCoordinates
Embora o parâmetro UIElement seja opcional, o método gera uma exceção se um UIElement não é fornecido quando hospedado em uma ilha.
Especifique o uiElement.XamlRoot como UIElement, em vez de deixá-lo em branco.
VisualTreeHelper.GetOpenPopups
Em aplicativos de Ilhas XAML, isso resultará em um erro. Em aplicativos AppWindow, isso retornará pop-ups abertas na janela principal.
VisualTreeHelper.GetOpenPopupsForXamlRoot(uiElement.XamlRoot)
FocusManager.GetFocusedElement FocusManager.GetFocusedElement(uiElement.XamlRoot)
contentDialog.ShowAsync() contentDialog.XamlRoot = uiElement.XamlRoot;
contentDialog.ShowAsync();
menuFlyout.ShowAt(null, new Point(10, 10)); menuFlyout.XamlRoot = uiElement.XamlRoot;
menuFlyout.ShowAt(null, new Point(10, 10));

Observação

Para o conteúdo XAML em um DesktopWindowXamlSource, existe um CoreWindow/Window no thread, mas ele sempre está invisível e tem um tamanho de 1x1. Ele ainda é acessível para o aplicativo, mas não retornará limites ou visibilidade significativas.

Para conteúdo XAML em um AppWindow, sempre haverá exatamente um CoreWindow no mesmo thread. Se você chamar uma API GetForCurrentView ou GetForCurrentThread, essa API retornará um objeto que reflete o estado do CoreWindow no thread, e não qualquer AppWindows que possa estar em execução nesse thread.

O que fazer e o que não fazer

  • Forneça um ponto de entrada claro para a exibição secundária utilizando o glifo "abrir nova janela".
  • Comunique aos usuários a finalidade da exibição secundária.
  • Assegure que o aplicativo seja totalmente funcional em uma única exibição e que os usuários abram uma exibição secundária apenas por conveniência.
  • Não conte com a exibição secundária para fornecer notificações ou outros elementos visuais transitórios.