Jakiś czas temu zdarzyło mi się napisać własny behavior, który w odróżnieniu od tych które dłubie na co dzień, może mieć zastosowanie w wielu aplikacjach, stąd też pomysł aby się nim podzielić :)
Co to są behaviorsy nie będę się rozpisywał w tym temacie. Zagadnienie jest większe, a do poczytania o nim polecam świetny artykuł: http://www.silverlightshow.net/items/Behaviors-and-Triggers-in-Silverlight-3.aspx
O co chodzi?
Skoro już wszyscy wiedzą co to są behaviorsy w Silverlight 3.0, to wypadało by powiedzieć że mój jest typu "TargetedTriggerAction", czyli wykonuje akcję na innym obiekcie gdy ten do którego jest przypisany, wywoła wybrany event.
Mój behavior po wciśnięciu przycisku "Enter" we wskazanym textboxsie zasymuluje wciśnięcie wskazanego przycisku (wszystko co dziedziczy z ButtonBase).
Pewnie pomyśleliście sobie od razu, co za bzdura, przecież można podpiąć event i wywołać tą samą metodę w kodzie. Tylko co w przypadku gdy namiętnie stosujemy MVVM, gdzie nasz "code behind" jest czyściutki i zawiera tylko konstruktor? W takim wypadku behavior jest tym czego poszukujemy. Co ważniejsze, "code behind" pozostaje nienaruszony, nie śmiecimy również w ViewModelu, a operacje "interfejsowe" pozostają ładnie oddzielone i nadają się do ponownego użycia.
Standardowe zastosowanie
Jak wspomniałem, behavior ma zastosowanie przede wszystkim w aplikacjach z wzorcem MVVM, a jego miejsce to np. pole wyszukiwania.
Dodajemy do aplikacji
<Button x:Name="TargetedButton" Content="Targeted Button" />
<TextBox Text="TextBox" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="KeyDown" >
<behavior:TextBoxEnterButtonInvoke TargetName="TargetedButton" />
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
, gdzie "i:" jest przestrzenią nazw dla "clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity", a "behavior:" dla projektu w którym umieszony jest kod bahaviora.
Kod źródłowy
Kodu jest niewiele, więc postanowiłem wkleić go cały.
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 System.Windows.Interactivity;
using System.Windows.Automation.Peers;
using System.Windows.Automation.Provider;
using System.Windows.Controls.Primitives;
/// TargetedTriggerAction for TextBox control.
/// Invokes targeted button when Enter is pressed inside TextBox.
///
/// Jacek Ciereszko
/// http://jacekciereszko.pl
///
///
namespace TextBoxEnterBehavior
{
public class TextBoxEnterButtonInvoke : TargetedTriggerAction
{
///
/// Gets or sets the peer.
///
///The peer.
private AutomationPeer _peer { get; set; }
///
/// Gets or sets the target button
///
private ButtonBase _targetedButton { get; set; }
///
/// Called after the TargetedTriggerAction is attached to an AssociatedObject.
///
///Override this to hook up functionality to the AssociatedObject.
protected override void OnAttached()
{
base.OnAttached();
_targetedButton = this.Target;
if (null == _targetedButton)
{
return;
}
// set peer
this._peer = FrameworkElementAutomationPeer.FromElement(_targetedButton);
if (this._peer == null)
{
this._peer = FrameworkElementAutomationPeer.CreatePeerForElement(_targetedButton);
}
}
///
/// Called after targeted Button change.
///
///Override this to hook up functionality to the new targeted Button.
protected override void OnTargetChanged(ButtonBase oldTarget, ButtonBase newTarget)
{
base.OnTargetChanged(oldTarget, newTarget);
_targetedButton = newTarget;
if (null == _targetedButton)
{
return;
}
// set peer
this._peer = FrameworkElementAutomationPeer.FromElement(_targetedButton);
if (this._peer == null)
{
this._peer = FrameworkElementAutomationPeer.CreatePeerForElement(_targetedButton);
}
}
///
/// Invokes the targeted Button when Enter key is pressed inside TextBox.
///
/// KeyEventArgs with Enter key
protected override void Invoke(object parameter)
{
KeyEventArgs keyEventArgs = parameter as KeyEventArgs;
if (null != keyEventArgs && keyEventArgs.Key == Key.Enter)
{
if (null != _peer)
{
IInvokeProvider invokeProvider = _peer.GetPattern(PatternInterface.Invoke) as IInvokeProvider;
invokeProvider.Invoke();
}
}
}
}
}
Do pobrania
Kod jest także dostępny do pobrania na stronie http://gallery.expression.microsoft.com/en-us/TextBoxInvokeButton.
Pozdrawiam,
Jacek Ciereszko


Brak komentarzy:
Prześlij komentarz