Skip to content
Bruno Sonnino
Menu
  • Home
  • About
Menu

Animando transições em WPF/Silverlight–Parte II–Usando Componentes

Posted on 14 January 2012

No post anterior vimos como animar uma transição usando código. Como falei, não acho aquela a melhor solução, pois obriga a usar code behind, o que não é de fácil manutenção. Poderíámos refatorar o código, criando uma classe para a animação e usá-la. Isto traria um pouco mais de separação, mas ainda teríamos de usar code behind.

Nesta segunda parte, usaremos um enfoque diferente: o uso de componentes prontos. Podemos usar diversos componentes, como o Kevin Bag-O-Tricks (https://github.com/thinkpixellab/bot), FluidKit (http://fluidkit.com), Silverlight Toolkit (http://silverlight.codeplex.com – só para Silverlight), o Transitionals (http://transitionals.codeplex.com).

Usaremos aqui o Transitionals, para WPF. Se quisermos fazer animações em Silverlight, devemos escolher outro dos componentes acima.

Seu uso é muito simples: após baixar o componente e adicionar uma referência ao projeto para a dll Transitionals.dll, devemos adicionar um componente TransitionElement no local onde queremos a animação, configurar a animação e colocar um conteúdo para o componente. Ao mudar o conteúdo, ocorre a transição selecionada.

Vamos então fazer o nosso projeto de animação. Crie um novo projeto WPF e adicione uma referência a Transitionals.dll. Em seguida, coloque um TransitionElement na grid principal:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*" />
        <RowDefinition Height="40" />
    </Grid.RowDefinitions>
    <transc:TransitionElement x:Name="TransitionBox">
    <transc:TransitionElement.Transition>
    <transt:TranslateTransition  StartPoint="1,0" EndPoint="0,0" Duration="0:0:1"/>
    </transc:TransitionElement.Transition>
    </transc:TransitionElement>
    <Button Width="65" Grid.Row="1" Content="Esconde" Margin="5" Click="Button_Click" />
</Grid>
XML

Devemos definir os namespaces para o TransitionElement e para a TranslateTransition na definição da janela:

<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:transc="clr-namespace:Transitionals.Controls;assembly=Transitionals"
        xmlns:transt="clr-namespace:Transitionals.Transitions;assembly=Transitionals"
        Title="MainWindow" Height="350" Width="525">
XML

Em seguida, é só colocar um conteúdo no TransitionElement:

<transc:TransitionElement x:Name="TransitionBox">
    <transc:TransitionElement.Transition>
        <transt:TranslateTransition  StartPoint="1,0" EndPoint="0,0" Duration="0:0:1"/>
    </transc:TransitionElement.Transition>
    <Grid Background="Red" />
</transc:TransitionElement>
XML

O código do botão muda o conteúdo do TrasitionElement e, com isso ativa a transição:

private void Button_Click(object sender, RoutedEventArgs e)
{
    TransitionBox.Content = new Grid() {Background = Brushes.Blue};
}
C#

Desta maneira, o código fica muito mais fácil, só precisamos mudar o conteúdo do elemento. Além disso, o componente Transitionals tem muitos tipos de transições, e podemos configurá-las de diversas maneiras. Por exemplo, o TranslateTrasition tem as propriedades StartPoint e EndPoint, dizendo onde começa e onde termina a transição. Para fazer da esquerda para direita, StartPoint deve ser –1,0 e EndPoint, 0,0. De cima para baixo, StartPoint deve ser 0,-1 e EndPoint, 0,0. Podemos inclusive fazer uma transição diagonal usando os pontos 1,1 e 0,0.

Eliminando o Code Behind

Uma das coisas que podem ser melhoradas aqui é a eliminação do code behind, usando o padrão de projeto MVVM. Para isso, usaremos o framework MVVM Light, que pode ser obtido gratuitamente em , ou ainda instalado diretamente no projeto usando o Nuget, uma extensão para o Visual Studio que facilita o download e instalação de bibliotecas e ferramentas no Visual Studio. Se você ainda não baixou o Nuget, vá imediatamente para e baixe-o. Vale a pena!

Uma vez instalado o Nuget, clique com o botão direito em References, no Solution Explorer e  selecione “Manage Nuget Packages”. Tecle “mvvm” na caixa de pesquisa e instale o pacote MVVM Light:

Isto instala o MVVM Light em nosso projeto, adiciona as referências necessárias e cria uma pasta ViewModel, com dois arquivos, MainViewModel.cs e ViewModelLocator.cs. MainViewModel.cs é o ViewModel referente à janela princiapl e ViewModelLocator é um localizador de ViewModel, referente à View.

Em MainViewModel.cs, colocamos uma propriedade, do tipo ViewModelBase, que conterá os ViewModel referente à View do conteúdo atual:

private ViewModelBase conteudo;

public ViewModelBase Conteudo
{
    get { return conteudo; }
    set
    {
        conteudo = value;
        RaisePropertyChanged("Conteudo");
    }
}
C#

Criaremos em seguida dois ViewModels, que serão referentes à nossas Views. Os dois ViewModels são muito semelhantes e têm apenas uma propriedade:

public class ViewModelA : ViewModelBase
{
    private string texto;

    public string Texto
    {
        get { return texto; }
        set
        {
            texto = value;
            RaisePropertyChanged("Texto");
        }
    }
}

public class ViewModelB : ViewModelBase
{
    private string texto;

    public string Texto
    {
        get { return texto; }
        set
        {
            texto = value;
            RaisePropertyChanged("Texto");
        }
    }
}
C#

Em seguida, crie no Solution Explorer um diretório chamado View e coloque lá dois UserControls, com apenas uma Grid com um TextBlock:

<UserControl x:Class="WpfApplication2.View.ViewA"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid Background="Red">
        <TextBlock Text="{Binding Texto}" FontSize="36" />
    </Grid>
</UserControl>
XML

Para eliminar o code behind, precisamos fazer um data binding da propriedade Content do TransitionElement com a propriedade conteúdo do ViewModel:

<transc:TransitionElement x:Name="TransitionBox" Content="{Binding Conteudo}">
    <transc:TransitionElement.Transition>
        <transt:TranslateTransition  StartPoint="1,0" EndPoint="0,0" Duration="0:0:1"/>
    </transc:TransitionElement.Transition>
</transc:TransitionElement>
XML

e eliminar o clique do botão, substituindo-o por um Command:

<Button Width="65" Grid.Row="1" Content="Esconde" Margin="5" Command="{Binding EscondeCommand}" />
XML

O command é definido no MainViewModel:

private ICommand escondeCommand;
public ICommand EscondeCommand
{
    get { return escondeCommand ?? (escondeCommand = new RelayCommand(MudaConteudo)); }
}

private void MudaConteudo()
{
    Conteudo = conteudo is ViewModelA ? 
        (ViewModelBase)new ViewModelB() { Texto = "ViewModel B"} : 
        (ViewModelBase)new ViewModelA() {Texto = " ViewModel A"};
}
C#

Finalmente, devemos definir o DataContext para a View principal:

<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:transc="clr-namespace:Transitionals.Controls;assembly=Transitionals"
        xmlns:transt="clr-namespace:Transitionals.Transitions;assembly=Transitionals" 
        Title="MainWindow" Height="350" Width="525"
        DataContext="{Binding Source={StaticResource Locator}, Path=Main}">
XML

Ao executar o programa, temos algo como mostrado na figura abaixo:

A view não é mostrada, apenas o nome da classe do conteúdo. Isso era de se esperar, pois a propriedade Conteúdo é do tipo ViewModelBase e sua representação é o método ToString(). Poderíamos ter colocado a View como sendo o conteúdo, mas isto vai contra o padrão MVVM: o ViewModel não deve conhecer a View. Uma solução para mostrar a View a partir do ViewModel é usar um recurso disponível no WPF ou no Silverlight 5: Data Templates implícitos. Em um Data Template implicito, não explicitamos a Key, apenas dizemos qual é o DataType e, com isso o WPF/Silverlight renderezam este DataTemplate toda vez que um conteúdo for do tipo referente a ele.

Definimos então os DataTemplates na seção Resources da janela:

<Window.Resources>
    <DataTemplate DataType="{x:Type ViewModel:ViewModelA}" >
        <View:ViewA />
    </DataTemplate>
    <DataTemplate DataType="{x:Type ViewModel:ViewModelB}" >
        <View:ViewB />
    </DataTemplate>
</Window.Resources>
XML

Agora, ao executar, temos a transição entre as duas views, sem o uso de code behind.

Conclusões

Usando componentes de animação de transições, temos a possibilidade de fazer transições muito sofisticadas, de maneira muito simples bastando mudar o conteúdo do componente.

Em seguida, vimos como tirar o código do code behind, colocando-o em um ViewModel, o que facilita na manutenção e permite maior testabilidade do código. Como bonus, vimos como usar implicit templates para ligar uma view a um viewmodel sem usar código. Este recurso está disponível apenas no WPF e no Silverlight 5. Embora você possa achar que não vale a pena (eliminamos apenas uma linha de código e incluímos dois viemodels, duas views, um novo componente MVVM, entre outros), minha intenção aqui foi mostrar como usar outros recursos, como a introdução do MVVM ao invés do code behind e como usar novos recursos, como o DataTemplate implícito. Numa aplicação maior, que requer maiores cuidados, estas mudanças se justificam plenamente.

Mas estas não são as únicas maneiras de se fazer transições de controles. Nos próximos artigos, veremos quais são as outras maneiras. Até lá!

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

  • May 2025
  • December 2024
  • October 2024
  • August 2024
  • July 2024
  • June 2024
  • November 2023
  • October 2023
  • August 2023
  • July 2023
  • June 2023
  • May 2023
  • November 2022
  • October 2022
  • September 2022
  • August 2022
  • June 2022
  • April 2022
  • March 2022
  • February 2022
  • January 2022
  • July 2021
  • June 2021
  • May 2021
  • April 2021
  • March 2021
  • February 2021
  • January 2021
  • December 2020
  • October 2020
  • September 2020
  • April 2020
  • March 2020
  • January 2020
  • November 2019
  • September 2019
  • August 2019
  • July 2019
  • June 2019
  • April 2019
  • March 2019
  • February 2019
  • January 2019
  • December 2018
  • November 2018
  • October 2018
  • September 2018
  • August 2018
  • July 2018
  • June 2018
  • May 2018
  • November 2017
  • October 2017
  • September 2017
  • August 2017
  • June 2017
  • May 2017
  • March 2017
  • February 2017
  • January 2017
  • December 2016
  • November 2016
  • October 2016
  • September 2016
  • August 2016
  • July 2016
  • June 2016
  • May 2016
  • April 2016
  • March 2016
  • February 2016
  • October 2015
  • August 2013
  • May 2013
  • February 2012
  • January 2012
  • April 2011
  • March 2011
  • December 2010
  • November 2009
  • June 2009
  • April 2009
  • March 2009
  • February 2009
  • January 2009
  • December 2008
  • November 2008
  • October 2008
  • July 2008
  • March 2008
  • February 2008
  • January 2008
  • December 2007
  • November 2007
  • October 2007
  • September 2007
  • August 2007
  • July 2007
  • Development
  • English
  • Português
  • Uncategorized
  • Windows

.NET AI Algorithms asp.NET Backup C# Debugging Delphi Dependency Injection Desktop Bridge Desktop icons Entity Framework JSON Linq Mef Minimal API MVVM NTFS Open Source OpenXML OzCode PowerShell Sensors Silverlight Source Code Generators sql server Surface Dial Testing Tools TypeScript UI Unit Testing UWP Visual Studio VS Code WCF WebView2 WinAppSDK Windows Windows 10 Windows Forms Windows Phone WPF XAML Zip

  • Entries RSS
  • Comments RSS
©2025 Bruno Sonnino | Design: Newspaperly WordPress Theme
Menu
  • Home
  • About