MVVM Как уйти от кода за событиями

После рассмотрения некоторых из наборов инструментов MVVM (MVVM Light, SimpleMVVM), общая тема, кажется, пытается использовать как можно больше смешиваемых событий, а не использовать codebehind.

Я не уверен, как сделать все события. Например, 2 события связываются при работе с Windows Phone 7.

  1. OnNavigatedTo / С
  2. В процессе

У кого-нибудь есть примеры как это сделать в MVVM? Я использую SimpleMVVM, но я надеюсь, что примеры могут быть похожими, и, возможно, легкий инструментарий MVVM или даже просто общее руководство по MVVM, показывающее, что это может помочь.

Я нашел только те, которые показывают, как сделать, как нажатие кнопки.

редактировать

Я вроде как запутался, когда использовать код за событиями или смешивать события с командами.

Например, в уроках MVVM Light они используют MVVM для навигации, но почему это лучше, чем использование события codebehind?

Я также немного растерялся, когда люди говорят

Codebehind не является злом; это сочетание бизнес-логики и кода, что является проблематичным. Пусть ваш пользовательский интерфейс обрабатывает задачи пользовательского интерфейса в вашем коде.

Хорошо в легких примерах MVVM у них есть "isbusy" в одном из примеров, где, когда список или что бы то ни было (забыл) загружает "появляется знак загрузки". Все это было сделано во ViewModel, а не в событии codebehind.

Так что мне это кажется противоречивым (может быть, я что-то упустил). Меня также озадачивает то, что если ViewModel ничего не знает о загрузке, как вы узнаете, когда загрузка началась или закончилась?

2 ответа

Решение

Как прокомментировал HighCore, используйте EventToCommand, Его довольно просто использовать, хотя сначала вам понадобится Blend SDK.

...
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.SL4"
xmlns:im="clr-namespace:Microsoft.Expression.Interactivity.Media;assembly=Microsoft.Expression.Interactions"
xmlns:ic="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions"
...
<i:Interaction.Triggers>
    <i:EventTrigger EventName="Loaded">
            <cmd:EventToCommand Command="{Binding GetTweetsCommand}" CommandParameter="Twitter" />
        </i:EventTrigger>
</i:Interaction.Triggers>

Кроме того, просто общее замечание по поводу кода: наличие функциональности, связанной с пользовательским интерфейсом, в коде позади - не самая плохая вещь в мире! Он отделен от вашей ViewModel и находится в логическом месте. Тем не менее, я считаю, что поведение легче тестировать. Например, используя класс, наследующий от TargetedTriggerAction позволяет управлять раскадровкой как изменениями свойств, так и элементами управления:

public class ImageAnimationTrigger : TargetedTriggerAction<Storyboard>
{
    protected override void Invoke(object parameter)
    {
        if (Target == null)
            return;

        if (parameter is DependencyPropertyChangedEventArgs)
        {
            DependencyPropertyChangedEventArgs args = (DependencyPropertyChangedEventArgs)parameter;

            if ((bool)args.NewValue)
                Target.Begin();
            else
                Target.Stop();
        }
        else if (parameter is RoutedEventArgs)
        {
            RoutedEventArgs args = (RoutedEventArgs)parameter;

            if (!(args.OriginalSource as Button).IsEnabled)
                Target.Begin();
            else
                Target.Stop();
        }
    }
}

Я использую это поведение с PropertyChangedTrigger следующее:

<i:Interaction.Triggers>
    <ic:PropertyChangedTrigger Binding="{Binding Loading}">
        <behav:ImageAnimationTrigger TargetName="animStoryboard" />
    </ic:PropertyChangedTrigger>
</i:Interaction.Triggers>

Как говорит Лоран Бюньон, используйте код, если вам нужно!

1) К сожалению, я не нашел хороших примеров, поэтому ты сам по себе.

2) если вы оставите свой код позади (используя команды вместо нажатия кнопок), вы сконцентрируете свой код только в ViewModel. Я вижу две преимущества:

а) если вы используете одну ViewModel для разных видов (и имеете несколько общих команд в нескольких играх),

б) если вы используете некоторые закрытые переменные / методы вашей ViewModel, которые недоступны в представлении.

3) Вы можете использовать RaisePropertyChanged для загрузки (перезагрузки) данных, загрузки данных в конструкторе ViewModel, чтобы избежать использования OnNavigatedTo или чего-то еще.

Другие вопросы по тегам