Skip to content
Bruno Sonnino
Menu
  • Home
  • About
Menu

Animando transições em WPF/Silverlight–Parte IV–Behaviors

Posted on 21 January 2012

No último post mostramos como animar transições usando o Blend e Visual States. Uma parte importante naquele mecanismo é o uso de behaviors. Com behaviors, podemos executar ações bastante complexas, apenas arrastando um behavior para um componente da janela. Isto, além de poderoso, traz outros benefícios:

  • É reutilizável. Podemos incluir o mesmo behavior em diversas situações
  • Permite que os designers possam incluir funcionalidade no design sem necessidade de código

Temos dois tipos de behaviors:

  • Actions – executam uma ação associado a um evento. Por exemplo, você pode criar uma Action que, associada a uma TextBox, emite um “click” a cada tecla pressionada, ou outra action que faz um controle crescer quando o mouse está sobre ele
  • Full behaviors – neste caso, há um comportamento mais complexo, não necessariamente associado a um único trigger. Um exemplo disso é o MouseDragElementBehavior, que permite movimentar um elemento, arrastando-o com o mouse

No Blend, encontramos os dois tipos de behaviors, com o final do nome indicando o tipo (ex. CallMethodAction ou FluidMoveBehavior).

Além dos pré-instalados, você pode encontrar outros behaviors, na galeria do Blend, em (quando verifiquei, existiam 114 behaviors disponíveis lá).

Os behaviors estão associados a um objeto e podem ter propriedades adicionais, além do trigger que os ativa. Por exemplo, o GoToStateAction tem como propriedades adicionais o componente destino e o estado a ser ativado, além da propriedade booleana UseTransitions, para usar as transições para mudar de um estado a outro.

Além de configurar as propriedades da Action, você pode especificar condições para que ela possa ser ativada. Por exemplo, usando o projeto do post anterior, podemos usar uma checkbox para permitir a ativação da transição. Para isso, basta clicar no botão “+” de Condition List, clicar no botão de propriedades avançadas da condição, criar um Data Binding com a checkbox e fazer um binding com a propriedade IsChecked. Desta maneira, a animação só será ativada se a checkbox estiver checada.

Além das Actions padrão, podemos criar Actions personalizadas para fazer o que queremos. No post anterior, usamos as Actions padrão, mas precisamos criar os Visual States. Além disso, temos um outro inconveniente: se quisermos fazer as animações para cima ou para baixo, temos que criar novos Visual States. Assim, criaremos nossa Action para fazer o que queremos, sem a necessidade de configuração especial.

No Visual Studio, crie um novo projeto WPF. Vamos adicionar agora a nossa Action. O Visual Studio, por padrão, não tem o template para criar uma Action. Poderíamos fazer isso usando o Blend. Ao abrir o projeto no Blend e selecionar a aba Project, você pode dar um clique com o botão direito do mouse, selecionar Add New Item e adicionar uma Action ao projeto.

Outra maneira de fazer isso é usar os templates online do Visual Studio. No Solution Explorer do Visual Studio, clique com o botão direito do mouse no projeto e selecione Add New Item. Na tela, vá para Online Templates e tecle action na caixa de pesquisa. Selecione o template C# Action Template for WPF e dê o nome de TransitionControlAction.

O template adiciona uma referência a System.Windows.Interactivity e gera uma classe semelhante a este código:

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Interactivity;
namespace WpfApplication4
{
//
// If you want your Action to target elements other than its parent, extend your class
// from TargetedTriggerAction instead of from TriggerAction
//
    public class TransitionControlAction : TriggerAction<DependencyObject>
{
public TransitionControlAction()
{
// Insert code required on object creation below this point.
        }
    protected override void Invoke(object o)
    {
        // Insert code that defines what the Action will do when triggered/invoked.
        }
}
}
C#

Temos dois tipos de actions: TriggerAction e TargetedTriggerAction. TriggerAction é uma action que não se refere a outro controle. Por exemplo, se quisermos criar uma action que executa o Notepad quando acontece um evento, usaríamos uma TriggerAction. TargetedTriggerAction refere-se a um outro elemento, chamado de Target. Este elemento é uma propriedade da action e pode ser acessado no Blend. Nós iremos criar uma TargetedTriggerAction. Portanto devemos mudar o código para derivar de TargetedTriggerAction, como mostra o comentário no início da classe. Esta action irá executar o mesmo código que criamos no primeiro post para fazer a animação. Devemos alterar também o tipo de objeto em que ela atua. Usaremos o FrameworkElement, pois este elemento tem as propriedades ActualWidthe ActualHeight.

public class TransitionControlAction : TargetedTriggerAction<FrameworkElement>
C#

Inicialmente, iremos criar a enumeração para as posições e duas DependencyProperties com o tipo de animação desejada e a duração, de modo que ela possa ser selecionada no Blend.

public enum TipoAnimacao
{
    Direita,
    Esquerda,
    Cima,
    Baixo
}

[Category("Common Properties")]
public TipoAnimacao Tipo
{
    get { return (TipoAnimacao)GetValue(TipoProperty); }
    set { SetValue(TipoProperty, value); }
}

public static readonly DependencyProperty TipoProperty =
    DependencyProperty.Register("Tipo", typeof(TipoAnimacao), typeof(TransitionControlAction));

[Category("Common Properties")]
public TimeSpan Duracao
{
    get { return (TimeSpan)GetValue(DuracaoProperty); }
    set { SetValue(DuracaoProperty, value); }
}

public static readonly DependencyProperty DuracaoProperty =
    DependencyProperty.Register("Duracao", typeof(TimeSpan), typeof(TransitionControlAction), 
    new UIPropertyMetadata(TimeSpan.FromMilliseconds(500)));
C#

Note que colocamos o atributo Category nas propriedades Tipo e Duraçãopara que elas apareçam junto com o grupo Common Properties. Ao compilarmos o projeto e abri-lo no Blend, vemos que nossa action aparece na aba Assets.

Ao arrastarmos uma TransitionControlAction para um botão, as propriedades aparecem no editor de propriedades:

Mas nossa action ainda não faz nada. Para fazer algo, devemos sobrescrever o método Invoke da action, colocando ali o código que deve ser executado. Usaremos o código que escrevemos na primeira postagem, modificando um pouco para usar o controle Target:

private void AnimaControle(FrameworkElement controle, TimeSpan duração, TipoAnimacao tipo)
{
    double xFinal = 0;
    double yFinal = 0;
    if (tipo == TipoAnimacao.Esquerda)
        xFinal = -controle.ActualWidth;
    else if (tipo == TipoAnimacao.Direita)
        xFinal = controle.ActualWidth;
    else if (tipo == TipoAnimacao.Cima)
        yFinal = -controle.ActualHeight;
    else if (tipo == TipoAnimacao.Baixo)
        yFinal = controle.ActualHeight;
    // cria a transformação e atribui ao controle
    var translate = new TranslateTransform(0, 0);
    controle.RenderTransform = translate;
    // cria a animação e anima-a
    if (tipo == TipoAnimacao.Esquerda || tipo == TipoAnimacao.Direita)
    {
        var da = new DoubleAnimation(0, xFinal, new Duration(duração));
        translate.BeginAnimation(TranslateTransform.XProperty, da);
    }
    else
    {
        var da = new DoubleAnimation(0, yFinal, new Duration(duração));
        translate.BeginAnimation(TranslateTransform.YProperty, da);
    }
}
C#

Finalmente, basta chamar o método AnimaControle a partir do método Invoke:

protected override void Invoke(object o)
{
    AnimaControle(Target, Duracao, Tipo);
}
C#

Com isto, nosso behavior está completo. Podemos abrir o projeto no Blend, arrastar a action para o botão, configurar o objeto Target apontando para a grid e executar o projeto. Ao clicar o botão, a grid faz uma transição animada para a direção selecionada. Note que não precisamos fazer nada. Basta arrastar a action para o botão, configurar o elemento Target e as propriedades. A action está pronta para ser executada.

Conclusão

Foi um longo trajeto até aqui. Vimos quatro maneiras diferentes de animar a transição, começamos com código e terminamos usando o mesmo código. No meio do caminho vimos diversos conceitos: partir de um código fixo para um código mais refatorado e flexível, usar componentes para transição, eliminar o code behind usando MVVM, usando o Nuget, Templates Implícitos, usar Visual States para criar animações sem usar código e, finalmente, behaviors, para criar ações que podem ser usadas por designers, de maneira flexível e sem usar código. Espero que tenham gostado!

1 thought on “Animando transições em WPF/Silverlight–Parte IV–Behaviors”

  1. Pingback: Behaviors em Blend – Bruno Sonnino

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