Ciclo de vida do aplicativo WPF vs. Xamarin.Forms

O Xamarin.Forms usa muitas diretrizes de design das estruturas baseadas em XAML que vieram antes dela, especialmente do WPF. No entanto, de outras maneiras, ele se desvia significativamente, o que pode ser um ponto pegajoso para as pessoas que tentam migrar. Este documento tenta identificar alguns desses problemas e fornecer diretrizes sempre que possível para conectar o conhecimento do WPF ao Xamarin.Forms.

Ciclo de vida do aplicativo

O ciclo de vida do aplicativo entre o WPF e o Xamarin.Forms é semelhante. Ambos começam no código externo (plataforma) e iniciam a interface do usuário por meio de uma chamada de método. A diferença é que o Xamarin.Forms sempre começa em um assembly específico da plataforma que inicializa e cria a interface do usuário para o aplicativo.

WPF

  • Main method > App > MainWindow

Observação

O Main método é, por padrão, gerado automaticamente e não visível no código.

Xamarin.Forms

  • iOSMain method > AppDelegate > App > ContentPage
  • AndroidMainActivity > App > ContentPage
  • UWPMain method > App(UWP) > MainPage(UWP) > App > ContentPage

Classe de aplicativo

O WPF e o Xamarin.Forms têm uma Application classe criada como singleton. Na maioria dos casos, os aplicativos derivarão dessa classe para fornecer um aplicativo personalizado, embora isso não seja estritamente necessário no WPF. Ambos expõem uma Application.Current propriedade para localizar o singleton criado.

Propriedades globais + persistência

O WPF e o Xamarin.Forms têm um Application.Properties dicionário disponível onde você pode armazenar objetos globais no nível do aplicativo que podem ser acessados em qualquer lugar do aplicativo. A principal diferença é que o Xamarin.Forms persistirá todos os tipos primitivos armazenados na coleção quando o aplicativo for suspenso e os recarregará quando ele for relançado. O WPF não dá suporte automaticamente a esse comportamento – em vez disso, a maioria dos desenvolvedores dependia do armazenamento isolado ou utilizava o suporte interno Settings .

Definindo páginas e a Árvore Visual

O WPF usa o Window como o elemento raiz para qualquer elemento visual de nível superior. Isso define um HWND no mundo do Windows para exibir informações. Você pode criar e exibir quantas janelas quiser simultaneamente no WPF.

No Xamarin.Forms, o visual de nível superior é sempre definido pela plataforma – por exemplo, no iOS, é um UIWindow. O Xamarin.Forms renderiza seu conteúdo nessas representações de plataforma nativa usando uma Page classe . Cada Page um no Xamarin.Forms representa uma "página" exclusiva no aplicativo, em que apenas uma é visível por vez.

Os WPFs Window e o Xamarin.Forms Page incluem uma Title propriedade para influenciar o título exibido e ambos têm uma Icon propriedade para exibir um ícone específico para a página (Observe que o título e o ícone nem sempre são visíveis no Xamarin.Forms). Além disso, você pode alterar as propriedades visuais comuns em ambos, como a cor da tela de fundo ou a imagem.

Tecnicamente, é possível renderizar para dois modos de exibição de plataforma separados (por exemplo, definir dois UIWindow objetos e ter o segundo renderizado para uma exibição externa ou AirPlay), ele requer código específico da plataforma para fazer isso e não é um recurso com suporte direto do próprio Xamarin.Forms.

Exibições

A hierarquia visual para ambas as estruturas é semelhante. O WPF é um pouco mais profundo devido ao seu suporte para documentos WYSIWYG.

WPF

DependencyObject - base class for all bindable things
   Visual - rendering mechanics
      UIElement - common events + interactions
         FrameworkElement - adds layout
            Shape - 2D graphics
            Control - interactive controls

Xamarin.Forms

BindableObject - base class for all bindable things
   Element - basic parent/child support + resources + effects
      VisualElement - adds visual rendering properties (color, fonts, transforms, etc.)
         View - layout + gesture support

Ciclo de vida de exibição

O Xamarin.Forms é orientado principalmente em cenários móveis. Dessa forma, os aplicativos são ativados, suspensos e reativados à medida que o usuário interage com eles. Isso é semelhante a clicar longe do Window em um aplicativo WPF e há um conjunto de métodos e eventos correspondentes que você pode substituir ou conectar para monitorar esse comportamento.

Finalidade Método WPF Método Xamarin.Forms
Ativação inicial ctor + Window.OnLoaded ctor + Page.OnStart
Mostrado Window.IsVisibleChanged Page.Appearing
Hidden Window.IsVisibleChanged Page.Disappearing
Suspender/Perder foco Window.OnDeactivated Page.OnSleep
Ativado/Tem foco Window.OnActivated Page.OnResume
Fechadas Window.OnClosing + Window.OnClosed n/d

Ambos também dão suporte à ocultação/exibição de controles filho, no WPF é uma propriedade IsVisible de três estados (visível, oculta e recolhida). No Xamarin.Forms, ele é visível ou oculto por meio da IsVisible propriedade .

Layout

O layout da página ocorre no mesmo 2-pass (Medida/Organização) que ocorre no WPF. Você pode conectar-se ao layout da página substituindo os seguintes métodos na classe Xamarin.Forms Page :

Método Finalidade
OnChildMeasureInvalidated O tamanho preferencial de um filho foi alterado.
OnSizeAllocated A página recebeu uma largura/altura.
Evento LayoutChanged O layout/tamanho da Página foi alterado.

Não há nenhum evento de layout global chamado hoje, nem há um evento global CompositionTarget.Rendering como encontrado no WPF.

Propriedades de layout comuns

O WPF e o Xamarin.Forms dão suporte Margin para controlar o espaçamento em torno de um elemento e Padding controlar o espaçamento dentro de um elemento. Além disso, a maioria das exibições de layout do Xamarin.Forms tem propriedades para controlar o espaçamento (por exemplo, linha ou coluna).

Além disso, a maioria dos elementos tem propriedades para influenciar como eles são posicionados no contêiner pai:

WPF Xamarin.Forms Finalidade
Horizontalalignment HorizontalOptions Opções esquerda/central/direita/stretch
Verticalalignment VerticalOptions Opções superior/central/inferior/stretch

Observação

A interpretação real dessas propriedades depende do contêiner pai.

Modos de exibição de layout

O WPF e o Xamarin.Forms usam controles de layout para posicionar elementos filho. Na maioria dos casos, eles são muito próximos uns dos outros em termos de funcionalidade.

WPF Xamarin.Forms Estilo de Layout
StackPanel StackLayout Empilhamento infinito da esquerda para a direita ou de cima para baixo
Grid Grid Formato tabular (linhas e colunas)
DockPanel n/d Encaixar nas bordas da janela
Tela AbsoluteLayout Posicionamento de pixel/coordenada
WrapPanel n/d Pilha de encapsulamento
n/d RelativeLayout Posicionamento relativo baseado em regra

Observação

O Xamarin.Forms não dá suporte a um GridSplitter.

Ambas as plataformas usam propriedades anexadas para ajustar os filhos.

Renderização

A mecânica de renderização para WPF e Xamarin.Forms é radicalmente diferente. No WPF, os controles criados renderizam diretamente o conteúdo em pixels na tela. O WPF mantém dois grafos de objeto (árvores) para representar isso : a árvore lógica representa os controles conforme definido em código ou XAML, e a árvore visual representa a renderização real que ocorre na tela que é executada diretamente pelo elemento visual (por meio de um método de desenho virtual) ou por meio de um XAML definido ControlTemplate que pode ser substituído ou personalizado. Normalmente, a árvore visual é mais complexa, pois inclui coisas como bordas em torno de controles, rótulos para conteúdo implícito etc. O WPF inclui um conjunto de APIs (LogicalTreeHelper e VisualTreeHelper) para examinar esses dois grafos de objeto.

No Xamarin.Forms, os controles que você define em um Page são, na verdade, apenas objetos de dados simples. Eles são semelhantes à representação de árvore lógica, mas nunca renderizam o conteúdo por conta própria. Em vez disso, eles são o modelo de dados que influencia a renderização de elementos. A renderização real é feita por um conjunto separado de renderizadores visuais que são mapeados para cada tipo de controle. Esses renderizadores são registrados em cada um dos projetos específicos da plataforma por assemblies do Xamarin.Forms específicos da plataforma. Você pode ver uma lista aqui. Além de substituir ou estender o renderizador, o Xamarin.Forms também tem suporte para Efeitos que podem ser usados para influenciar a renderização nativa por plataforma.

A árvore lógica/visual

Não há nenhuma API exposta para percorrer a árvore lógica no Xamarin.Forms, mas você pode usar Reflexão para obter as mesmas informações. Por exemplo, aqui está um método que pode enumerar filhos lógicos com reflexão.

Gráficos

O Xamarin.Forms inclui um sistema gráfico para desenhar primitivos, que é chamado de Formas. Para obter mais informações sobre formas, consulte Formas do Xamarin.Forms. Além disso, você pode incluir bibliotecas de terceiros, como SkiaSharp , para obter o desenho 2D multiplataforma.

Recursos

O WPF e o Xamarin.Forms têm o conceito de recursos e dicionários de recursos. Você pode colocar qualquer tipo de objeto em um ResourceDictionary com uma chave e, em seguida, pesquisá-lo por {StaticResource} coisas que não serão alteradas ou {DynamicResource} para coisas que podem mudar no dicionário em runtime. O uso e a mecânica são os mesmos com uma diferença: o Xamarin.Forms exige que você defina o ResourceDictionary para atribuir à propriedade, enquanto o Resources WPF cria previamente um e o atribui para você.

Por exemplo, consulte a definição abaixo:

WPF

<Window.Resources>
   <Color x:Key="redColor">#ff0000</Color>
   ...
</Window.Resources>

Xamarin.Forms

<ContentPage.Resources>
   <ResourceDictionary>
      <Color x:Key="redColor">#ff0000</Color>
      ...
   </ResourceDictionary>
</ContentPage.Resources>

Se você não definir o ResourceDictionary, um erro de runtime será gerado.

Estilos

Os estilos também têm suporte total no Xamarin.Forms e podem ser usados para criar o tema dos elementos do Xamarin.Forms que compõem a interface do usuário. Eles dão suporte a gatilhos (propriedade, evento e dados), herança por meio BasedOnde e pesquisas de recursos para valores. Os estilos são aplicados aos elementos explicitamente por meio da Style propriedade ou implicitamente por não fornecer uma chave de recurso , assim como o WPF.

Estilos de dispositivo

O WPF tem um conjunto de propriedades predefinidas (armazenadas como valores estáticos em um conjunto de classes estáticas, como SystemColors) que ditam cores, fontes e métricas do sistema na forma de valores e chaves de recurso. O Xamarin.Forms é semelhante, mas define um conjunto de Estilos de Dispositivo para representar as mesmas coisas. Esses estilos são fornecidos pela estrutura e definidos como valores com base no ambiente de runtime (por exemplo, acessibilidade).

WPF

<Label Text="Title" Foreground="{DynamicResource {x:Static SystemColors.DesktopBrushKey}}" />

Xamarin.Forms

<Label Text="Title" Style="{DynamicResource TitleStyle}" />