MVVM如何摆脱代码隐藏事件

时间:2013-02-18 18:14:16

标签: windows-phone-7 mvvm mvvm-light simple-mvvm

在查看了一些MVVM工具包(MVVM Light,SimpleMVVM)之后,共同的主题似乎尝试使用尽可能多的可混合事件而不使用代码隐藏。

我不确定如何做所有事件。例如,当做手机7时,2个事件就会被绑定。

  1. OnNavigatedTo / From
  2. 开启
  3. 有没有人有关于如何在MVVM中执行此操作的示例?我正在使用SimpleMVVM,但我希望这些示例可能类似,可能是MVVM轻量级工具包,甚至只是一般的MVVM教程,显示这可能会有所帮助。

    我发现只显示按钮点击的方法。

    修改

    我对何时使用事件后面的代码或将混合事件用于命令感到困惑。

    例如在MVVM Light教程中,他们使用MVVM进行导航,但为什么这比使用代码隐藏事件更好?

    当人们说

    时,我也有点困惑
      

    Codebehind不是邪恶的;它是业务逻辑和代码隐藏的结合   这是有问题的。让您的UI处理代码隐藏中的UI任务。

    在MVVM灯光示例中,他们有" isbusy"在其中一个示例中,当列表或其他任何内容(忘记)正在加载"加载符号出现时#34;。这都是在ViewModel中完成的,而不是代码隐藏事件。

    所以这对我来说似乎有些矛盾(也许我错过了什么)。令我困惑的是,如果ViewModel对加载一无所知,你怎么知道加载何时开始或结束?

2 个答案:

答案 0 :(得分: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>

此外,只是关于代码隐藏的一般观点:在代码隐藏中使用与UI相关的功能并不是世界上最糟糕的事情!它与您的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>

正如Laurent Bugnion所说,如果需要,请使用代码隐藏!

答案 1 :(得分:0)

1)不幸的是,我没有找到好的例子,所以你是独立的。

2)如果将代码隐藏空白(通过使用命令而不是按钮单击),则只能将代码集中在ViewModel中。我可以看到两点好处:

a)如果您将一个ViewModel用于不同的视图(并且在几个视图中有一些常用命令),

b)如果您使用ViewModel的某些私有变量/方法,这些变量/方法在视图中不可用。

3)您可以使用RaisePropertyChanged加载(重新加载)数据,在ViewModel构造函数中加载数据以避免使用OnNavigatedTo或其他内容。