środa, 30 stycznia 2013

[WPF] Caliburn.Micro: Akcje

W tym poście nieco na temat sposobów, jak powiązać akcje użytkownika z widoku z handlerami z ViewModelu.

Najprostszy sposób to binding przez konwencje nazw, ale sposób ten nie zawsze wystarcza. Caliburn.Micro, dla niektórych wybranych kontrolek, wiąże atrybut x:Name (z Xaml) z funkcją o identycznej nazwie z ViewModelu. W ten sposób nie jesteśmy jednak w stanie sprecyzować, które zdarzenie z kontrolki nas interesuje. Twórcy uznali, że np. dla przycisku będzie to zdarzenie Click, które zdecydowanie najczęściej ma nieść za sobą określone akcje użytkownika. Zainteresowani, mogą przejrzeć domyślne bindingi w klasie ConventionManager.cs ze źródeł projektu Caliburn.Micro.

Inny bardziej złożony, ale dający więcej możliwości sposób wykorzystuje Triggery.

<Button Content="Print Name">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Click">
            <cal:ActionMessage MethodName="PrintName" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Button>

Dzięki konwencjom możemy sterować dostępnością przycisku. Wystarczy wprowadzić property o nazwie takiej samej jak akcja, lecz zawierającej z przodu człon Can. Property takie musi zwracać typ bool i być notyfikowane przy odpowiednich zmianach w modelu danych. Na przykład:

public class PersonDetailsViewModel : Screen, IHandle<NewPersonMessage>
{
    public bool CanPrintName
    {
        get { return Entity != null; }
    }

    public void Handle(NewPersonMessage message)
    {
        Entity = message.Entity;
        NotifyOfPropertyChange(() => CanPrintName);
    }

    public void PrintName()
    {
        MessageBox.Show(Entity.Name);
    }
}

Ostatnim sposobem zapisu, krótszym i umożliwiającym przekazywanie parametrów w prostszy sposób jest Message.Attach. Tutaj w pełnym zapisie możemy wybrać, które zdarzenie nas interesuje, oraz co chcemy przekazać przez parametr.

<Slider x:Name="Entity_Age" Maximum="100" VerticalAlignment="Stretch"
    cal:Message.Attach="[Event MouseEnter] = [Action IncrementAge($eventArgs)]" />

Poza eventArgs można przekazać kilka innych obiektów, między innymi związanych z data bindingiem. Opisane są w dokumentacji.

Brak komentarzy:

Prześlij komentarz