MVVM Как уйти от кода за событиями
После рассмотрения некоторых из наборов инструментов MVVM (MVVM Light, SimpleMVVM), общая тема, кажется, пытается использовать как можно больше смешиваемых событий, а не использовать codebehind.
Я не уверен, как сделать все события. Например, 2 события связываются при работе с Windows Phone 7.
- OnNavigatedTo / С
- В процессе
У кого-нибудь есть примеры как это сделать в 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 или чего-то еще.