Pokazywanie postów oznaczonych etykietą Behavior. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą Behavior. Pokaż wszystkie posty

niedziela, 2 maja 2010

Silverlight Center And Scale Behavior

W ostatnim poście pisałem o tym jak wyśrodkować i skalować aplikację. Tym razem poszedłem o krok dalej i stworzyłem prosty behavior który z łatwością podłączymy do każdej aplikacji i nie musimy modyfikować istniejącego kodu.

Co należy zrobić?
1. Ściągnąć kod bahaviora:  http://gallery.expression.microsoft.com/en-us/CenterAndScale
2. Podłączyć kod do aplikacji:
<usercontrol .....="" ....="" xmlns:behavior="clr-namespace:CenterAncScaleBehavior;assembly=CenterAncScaleBehavior" xmlns:interaction="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity">

    <interaction:interaction.behaviors>
        <behavior:centerancscalebehavior>
    </behavior:centerancscalebehavior>

    <grid> ... </grid>
</interaction:interaction.behaviors>
</usercontrol>
3. Gotowe. W 95% aplikacji powinno działać. :]

Jeżeli używacie Microsoft Expression Blend-a, wystarczy przeciągnąć klasę na aplikację (patrz video).

Prezentacja, a więc behavior w akcji (66 sekund)


Prosty przykład działania
Aplikacja bez behaviora:  http://bit.ly/cVinEC
Aplikacja już z podłączonym bahaviorem: http://bit.ly/ba8UsI

Nie bangla?
Behavior powinień działać dla więkoszości aplikacji ale niekoniecznie dla wszystkich. Jeśli macie specyficzne ustawienia, stałe rozmiary dla UserControl itp., to bez zmian w aplikacji niestety skalowanie nie zadziała.

Pozdrawiam,
Jacek Ciereszko

piątek, 2 października 2009

[Behaviors] Mouse Over ComboBox Open (Behavior)

Po ostatnim małym sukcesie (7 dni i ponad 700 ściągnięć) z behaviorsem (patrz poprzedni wpis), postanowiłem że gdy kolejny raz przyjdzie mi do głowy jakiś nowy prosty behavior, również się nim podzielę.

Prościej się nie da

Mój najnowszy behavior nie może być prostszy, bo poniżej jednej linii kodu która rzeczywiście coś robi, nie da się zejść ;) Na szczęście jego działanie stawia go w innym świetle. A o co chodzi? Otóż mój nowy behavior, jak nazwa tego wpisu sugeruje, otwiera listę ComboBoxa po najechaniu na nią myszką. Tada!!! :P

Live demo

Niby nic ale rzeczywiście przydaje się w wielu aplikacjach. Po co użytkownik ma klikać na listę żeby się rozwinęła, skoro może najechać na nią myszką, zawsze to o jeden click mniej! :)

Dodajemy do kodu

<ComboBox Height="29" Width="130" d:LayoutOverrides="Margin">
<interaction:Interaction.Behaviors>
<behavior:OpenComboBoxBehavior />
</interaction:Interaction.Behaviors>
<ComboBoxItem>
<TextBlock Text="First element" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="Second element" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="Third element" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="Fourth element" />
</ComboBoxItem>
</ComboBox>

, gdzie "i:" jest przestrzenią nazw dla "clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity", a "behavior:" dla projektu w którym umieszczony jest kod bahaviora.

Wady

Ten Behavior w ogóle nie nadaje się w interfejsach gdzie mamy wiele elementów i ciągle rozwijająca się lista tylko by zasłaniała pozostałe elementy, natomiast jest świetny w paskach menu, przyciskach z dodatkowymi opcjami itp.

Inspiracja

Oczywiście sam na taki pomysł ulepszenie ergonomii interfejsu nie wpadłem, a zwyczajnie podpatrzyłem go na stronie youtube.com. :) Jeżeli przyjrzycie się swojemu użytkownikowi w prawym górnym rogu, to zobaczycie że jak najedziecie na swój profil myszką, to bez klikania rozwija się bardzo wygodna lista dodatkowych opcji.

Source Code

Tradycyjnie, ponieważ kod jest krótki, wklejam całość.

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;

/// Behavior for ComboBox control.
/// It invokes drop down list when mouse is over it.
///
/// Jacek Ciereszko
/// http://geekswithblogs.net/SilverBlog/
///

///

namespace ComboBoxBehavior
{
public class OpenComboBoxBehavior : Behavior
{
///
/// Called after the Behavior is attached to an AssociatedObject.
///

/// Override this to hook up functionality to the AssociatedObject.
protected override void OnAttached()
{
base.OnAttached();
this.AssociatedObject.MouseEnter += new MouseEventHandler(AssociatedObject_MouseEnter);
}

///
/// Called after the Behavior is detached from an AssociatedObject.
///

/// Override this to hook up functionality to the AssociatedObject.
protected override void OnDetaching()
{
this.AssociatedObject.MouseEnter -= new MouseEventHandler(AssociatedObject_MouseEnter);
base.OnDetaching();
}

///
/// When mouse is over ComboBox, control drop down will open
///

///
///
void AssociatedObject_MouseEnter(object sender, MouseEventArgs e)
{
this.AssociatedObject.IsDropDownOpen = true;
}
}
}

Do pobrania

Kod jest także dostępny do pobrania na stronie http://gallery.expression.microsoft.com/en-us/OpenComboBoxDropDown.


Pozdrawiam,

Jacek Ciereszko

poniedziałek, 21 września 2009

[Behaviors] TextBox Enter Button Invoke (TargetedTriggerAction)

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.

Live demo

Wciskając "Enter" w polu tekstowym otrzymujemy ten sam efekt co wciskając przycisk.

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