Para começar, é necessário incluir no seu projeto uma referencia para o assembly Microsoft.Expression.Interactivity.dll, este assembly fica localizado na pasta {Program Files}\Microsoft Expression\Blend 3 Preview\Libraries\Silverlight\Microsoft.Expression.Interactivity.dll ( ou pode ser baixado através do link ). Por algum motivo este assembly não faz parte do SDK do Silverlight até o momento.
Dentro deste assembly existem 3 classes que voce pode usar como base para criar seus proprios behaviors:
- Behavior: Behavior simples
- TriggerAction: Behavior disparado com eventos
- TargettedTriggerAction: Behavior disparado com eventos que afeta objetos separados ( Targets )
O diagrama de classe fica da seguinte maneira:
Neste post vamos criar um behavior simples que usa como base a classe Behavior. Para behaviors simples esta classe é perfeita, o unico trabalho que temos que fazer é implementar dois metodos para notificar o behavior quando ele é anexado e desanexado de um objeto. Eu decidi criar um behavior que será aplicado em Panels ( Componentes que são usados para gerenciamento de layout: Canvas, StackPanel e Grid ), a ideia deste behavior é que quando o usuário entrar com o mouse sobre um dos filhos do panel ( componentes dentro do panel: button,list,... ), os outros fiquem transparente ( próximo do invisivel ), e quando o usuário sair com o mouse, os filhos voltem com sua cor original.
Então para começar crie uma classe que extende a classe Behavior, eu dei o nome de PanelFocusBehavior.
public class PanelFocusBehavior : Behavior
O metodo Behavior possui 2 metodos (OnAttached e OnDetaching) que vamos sobrescrever para adicionar
a nossa lógica.
OnAttached: Este método é executado no momento em que o behavior é associado a um objeto da aplicação.
OnDetaching: Este metodo é executado quando o a associação entre o behavior e o objeto deixa de existir.
Veja a implementação do método OnAttached para o nosso behavior:
private Panel panel;
private Dictionary childrenOpacityMask;
protected override void OnAttached()
{
base.OnAttached();
panel = this.AssociatedObject;
childrenOpacityMask = new Dictionary();
panel.Loaded += new RoutedEventHandler(panel_Loaded);
}
void panel_Loaded(object sender, RoutedEventArgs e)
{
foreach (UIElement children in panel.Children)
{
children.MouseEnter += new MouseEventHandler(children_MouseEnter);
children.MouseLeave += new MouseEventHandler(children_MouseLeave);
childrenOpacityMask.Add(children, children.OpacityMask);
}
}
Veja que no metodo OnAttached a única coisa que fazemos é guardar a referencia para o Panel que esta
sendo associado ao nosso behavior e adicionar um handler para o evento Loaded deste panel.
No metodo panel_Loaded percorremos todos os filhos ( objetos dentro do panel ) e adicionamos um handler
para o evento MouseEnter e outro para o evento MouseLeave. Também adicionamos em um Dictionary a mascara
original do objeto ( Este passo é importante para que o aspecto original do objeto seja mantido durante a
execução do behavior ).
Ok, depois de iniciarmos o behavior e adicionar um handler para os eventos dos filhos, o que falta?
Falta ainda, realizar as alterações que havia idealizado para o Panel. Veja a lógica dos metodos MouseEnter e MouseLeave.
void children_MouseEnter(object sender, MouseEventArgs e)
{
Brush oldOpacityMask;
SolidColorBrush opacityMask = new SolidColorBrush(Color.FromArgb(40,255,255,255));
foreach (UIElement children in panel.Children)
{
children.OpacityMask = opacityMask;
}
UIElement elementSender = (sender as UIElement);
if (childrenOpacityMask.TryGetValue(elementSender, out oldOpacityMask) == true)
{
elementSender.OpacityMask = oldOpacityMask;
}
}
void children_MouseLeave(object sender, MouseEventArgs e)
{
foreach (UIElement children in panel.Children)
{
restoreColor(children);
}
}
private void restoreColor(UIElement element)
{
Brush opacityMask;
if (childrenOpacityMask.TryGetValue(element, out opacityMask) == true)
{
element.OpacityMask = opacityMask;
}
}
No metodo children_MouseEnter percorremos todos os objetos que estão no panel e trocamos
a OpacityMask de cada um para um SolidColorBrush com alpha 40. Depois de percorrer todos, voltamos a
mascara do objeto que disparou o evento para sua mascara original ( deste modo somente ele irá permanecer
com sua aparencia original )
No metodo children_MouseLeave percorremos todos os objetos que estão no panel e voltamos
sua mascara original.
O metodo restore color, só serve para voltar a aparencia original de um objeto.
Ok. Nós já vimos no post anterior como aplicar os behaviors. Portanto agora basta adicionar este behavior
em um Panel qualquer e testar. Veja figura do nosso behavior em ação.
Para quem não conseguiu acompanhar o tutorial, veja o código completo do nosso Behavior:
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Expression.Interactivity;
using System.Collections;
using System.Collections.Generic;
namespace BehaviorsDemo
{
public class PanelFocusBehavior : Behavior
{
private Panel panel;
private Dictionary childrenOpacityMask;
protected override void OnAttached()
{
base.OnAttached();
panel = this.AssociatedObject;
childrenOpacityMask = new Dictionary();
panel.Loaded += new RoutedEventHandler(panel_Loaded);
}
void panel_Loaded(object sender, RoutedEventArgs e)
{
foreach (UIElement children in panel.Children)
{
children.MouseEnter += new MouseEventHandler(children_MouseEnter);
children.MouseLeave += new MouseEventHandler(children_MouseLeave);
childrenOpacityMask.Add(children, children.OpacityMask);
}
}
protected override void OnDetaching()
{
foreach (UIElement children in panel.Children)
{
children.MouseEnter -= new MouseEventHandler(children_MouseEnter);
children.MouseLeave -= new MouseEventHandler(children_MouseLeave);
restoreColor(children);
}
}
void children_MouseLeave(object sender, MouseEventArgs e)
{
foreach (UIElement children in panel.Children)
{
restoreColor(children);
}
}
void children_MouseEnter(object sender, MouseEventArgs e)
{
Brush oldOpacityMask;
SolidColorBrush opacityMask = new SolidColorBrush(Color.FromArgb(40,255,255,255));
foreach (UIElement children in panel.Children)
{
children.OpacityMask = opacityMask;
}
UIElement elementSender = (sender as UIElement);
if (childrenOpacityMask.TryGetValue(elementSender, out oldOpacityMask) == true)
{
elementSender.OpacityMask = oldOpacityMask;
}
}
private void restoreColor(UIElement element)
{
Brush opacityMask;
if (childrenOpacityMask.TryGetValue(element, out opacityMask) == true)
{
element.OpacityMask = opacityMask;
}
}
}
}
O interessante é que agora podemos adicionar este comportamento em qualquer Panel da nossa aplicação sem a necessidade de alterar código. Basta arrastar o Behavior e pronto.
Nos próximos posts sobre o tema vamos ver como criar Behaviors através da classe TriggerAction.