一开始做MVVM的程序时,就知道有现成的框架,但个人并没有使用。做着做着就发现MVVM模式有一个最大的问题:代码量远远超出了不用MVVM模式做的程序。这些代码感觉就是一些重复的代码,但又没办法省略。后来终于知道,原来框架就能解决这个问题。
Stylet是一款很轻量却功能强大的WPF MVVM框架,了解了一下,感觉还不错。不过一开始,我就遇到了一些无解的问题:
1、当制作无边框窗口时(也就是WindowStyle为None),你在ViewModel根本没办法让窗口最大化、最小化等。
2、拖动窗口,让某个控件获得焦点,到目前也没有找到办法。
当然,除了这些(这些在不使用Stylet的时候要实现也是很复杂的,只是用Stylet之后更是无从下手),Stylet的确让我们减少了极大的代码编写工作量。
Stylet的文档里面,建议我们直接把*.xaml.cs文件删除,因为他觉得完全不需要。但就目前我遇到的问题来看,这些cs文件还是保留下来比较好。MVVM模式在最理想的情况下,View层和逻辑代码是完全分开的,也就是*.xaml.cs里不要写任何代码。但有的时候,为了做到这一点,需要付出极大的代价(例如本来的this.WindowState=WindowState.Minimize语句需要用几十行代码实现)。其实追根到底,MVVM模式的目的就是为了让程序的可维护性更好。让窗口最小化、最大化、或是拖动窗口、改变窗口大小这种代码,几乎是不会有什么问题的,也没有什么维护的问题。所以个人觉得,此类代码,如果实在没有办法,放在*.xaml.cs里也关系不大。
一、属性书写的简化
使用MVVM模式,在ViewModel里面,每个属性都几乎要这么写:
private int property1;
public int Property1
{
get
{
return property1;
}
set
{
property1 = value;
RaisePropertyChanged("Property1");
}
}
private int property2;
public int Property2
{
get
{
return property2;
}
set
{
property2 = value;
RaisePropertyChanged("Property2");
}
}
有没有觉得很烦?反正我是写得烦了。这个问题的解决办法其实跟Stylet也没有什么关系,只是我在使用Stylet的时候才发现的。我们需要用到一个叫做PropertyChanged.Fody的NuGet包。我的程序.NET版本是4.5,下载最新的版本会有问题。建议使用1.50.3的版本。
加入PropertyChanged.Fody包之后,不用写任何代码,公开的属性自然就会通知跟它绑定的控件。我们的代码可以变成这样:
public int Property1{get;set;}
public int Property2{get;set;}
是不是这样感觉好多了!
二、事件书写的简化
没错,用MVVM模式,写事件也是很烦人的。我们来比较一下:
非MVVM模式,XAML端:
<Button Name="Minimize" Content="最小化" Click="Minimize_Click"/>
MVVM模式,XAML端:
<Button Content="登录">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<c:EventCommand Command="{Binding LoginClick}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
非MVVM模式,XAML.CS:
private void Maximize_Click(object sender, RoutedEventArgs e)
{
//代码
}
MVVM模式,ViewModel:
private BaseCommand loginClick;
public BaseCommand LoginClick
{
get
{
if (loginClick == null)
{
loginClick = new BaseCommand(new Action<object>(o =>
{
//代码
}));
}
return loginClick;
}
}
有没有觉得很烦?反正我是写得烦了。使用Stylet之后,这个状况可以得到极大的改善。MVVM模式的写法就像非MVVM模式的写法一样。具体怎么做,Stylet的作者已经写了很详细的文档,还有示例,读者可以参考。我只打算写一些使用Stylet过程中遇到的一些比较麻烦的问题和一些注意事项。