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
- iOS –
Main method > AppDelegate > App > ContentPage
- Android –
MainActivity > App > ContentPage
- UWP –
Main 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 BasedOn
de 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}" />