WPF编程方法论

67

在我的APP中,我使用了我工具正在管理的软件的API。我有一个包含16个类的DAL,其中3个是单例模式。我在.cs文件和XAML中有一些逻辑。

我的问题是,我看到很多评论说用WPF编写的应用程序应该使用MVVM,这将使代码更可用和可读。我能否将我的代码转换为MVVM?MVVM的实际含义是什么(不是维基百科或手册定义)?

我还使用SQL查询,并阅读了一篇关于EF(Entity Framework)的论文。MVVM和EF是否可以在同一个项目中共存?


6
阅读这篇来自MSDN杂志的关于MVVM的优秀文章:http://msdn.microsoft.com/zh-cn/magazine/dd419663.aspx - acrilige
实际上,EF 和 WPF 喜欢一起玩。 - user853710
4个回答

131

MVVM的实际含义是:UI不是数据。数据是数据,UI是UI。

这意味着您不应该以程序逻辑(通常称为业务逻辑)与UI组件的状态紧密耦合或依赖的方式开发应用程序,而应该使其依赖于数据项的状态(无论是模型还是视图模型)。

例如,在其他框架(如winforms)中,如果您有一个包含文本框和按钮的屏幕,通常会向按钮添加单击事件处理程序,然后从文本框读取文本。在MVVM中,TextBox的Text属性应绑定到ViewModel中的字符串属性,按钮也应绑定到ViewModel中的命令。

这允许UI的抽象(即ViewModel),因此,正如我之前所说,您的应用程序逻辑可以依赖于UI的抽象,而不是UI本身。

这允许UI和逻辑具有巨大的可伸缩性,并且还允许测试UI行为的多个方面,因为UI行为的很大一部分是在ViewModel中定义的。

还有其他方面的MVVM,但主要认识是:

编辑:

为了完整起见,我将添加一个具体的示例:

1 - 非MVVM WPF:

XAML:

<StackPanel>
   <TextBox x:Name="txtLastName"/>
   <Button Content="Click Me" Click="Button_Click"/>
</StackPanel>

后台代码:

private void Button_Click(object sender, EventArgs e)
{
    //Assuming this is the code behind the window that contains the above XAML.
    var lastname = this.txtLastName.Text; 

    //Here you do some actions with the data obtained from the textbox
}

2 - MVVM WPF:

XAML:

<StackPanel>
   <StackPanel.DataContext>
       <my:MyViewModel/>
   </StackPanel.DataContext>
   <TextBox Text="{Binding LastName}"/>
   <Button Content="Click Me" Command="{Binding MyCommand}"/>
</StackPanel>

视图模型:

public class MyViewModel
{
    public string LastName { get; set; }

    public Command MyCommand { get; set; }

    public MyViewModel()
    {
        // The command receives an action on the constructor,
        // which is the action to execute when the command is invoked.
        MyCommand = new Command(ExecuteMyCommand); 
    }

    private void ExecuteMyCommand()
    {
        //Only for illustration purposes, not really needed.
        var lastname = this.LastName; 

        //Here you do some actions with the data obtained from the textbox
    }
}

从上面的例子中可以看出,ViewModel根本没有与View有任何关联,因此只要保持Bindings不变,View可以是任何东西。

使它们神奇地协同工作的粘合剂是WPF UI元素的DataContext属性,它是所有绑定将被解析为的对象。

还有其他一些东西,例如在ViewModel中启用双向绑定的属性更改通知,但这超出了本答案的范围。

还要记住,MVVM是一种设计模式,而WPF是一个框架。MVVM目前也应用在其他技术中(目前关于JavaScript等网络技术的MVVM有很多热议)。

我建议您阅读其他答案中提到的书籍以及这个教程,以了解更多关于WPF的特定方面。


我看过的关于这个主题最好的解释之一。谢谢。 - nawfal
我同意。这是关于WPF - MVVM重构主题的最佳回复之一。谢谢! - Majak

15
我的问题是,我看到很多评论说用WPF编写的应用程序应该使用MVVM,这样可以使代码更可用和易读,我能转换我的代码为MVVM吗?
没有必须使用MVVM模式的要求。您需要考虑正在构建的应用程序的复杂性和开发团队的技能集。一般来说,如果它是一个小型或中小型应用程序,则MVVM可能会过度设计。如果团队的技能/才能不适合分离的演示模式,则MVVM可能不是一个好决定。
如果正确执行,则MVVM可以为您提供所有类型的优势。相反,如果做得不好,则可能会成为开发和维护的噩梦-绝对不是更可读和可用的。从个人经验来看,我认为与基于MVVM的糟糕编写的应用程序相比,更容易处理糟糕的code-behind应用程序。
当然,您可以将当前的应用程序重写为MVVM模式。只需删除您的code-behind并将其放入您的视图模型、辅助类、存储库类、业务逻辑类等中。不要陷入将所有内容都放入view-models中的陷阱中,创建一个MVVM-美化的code-behind。
我还使用SQL查询,并阅读了关于EF(Entity Framework)的论文,MVVM和EF可以在同一项目中共存吗?
当然,它们可以。只需记住,EF是数据访问技术,而MVVM是设计模式。您可能会在所提到的DAL类中使用EF。
最后一个想法,如果您决定走MVVM路线,那么您应该考虑使用一个有利于它的框架,比如Prism。哦,还要准备好学习和挫折。

1
我同意@Big Daddy的观点,考虑使用一个框架。在我的情况下,我正在使用Caliburn.Micro(我最初使用Prism,但我发现它有点复杂)。就在一年前,我和你处于同样的境地,我决定改用MVVM,开始很困难,但现在一切都更加合乎逻辑、干净、有序,我很享受这个过程 :-) - Oscar Mateu
我同意应用程序大小和应用程序的目的(内部测试框架还是客户应用程序等)在决策中起着重要作用。但是一旦学会了mvvm模式(prism非常棒!),只需利用业余时间写几天mvvm与prism,我很可能现在会将其用于所有中型或大型项目。 - Josh
@Josh...这是一个很好的模式。问题在于,许多时候小应用程序会变得比预期的要大。如果MVVM没有被实施,那么我们可能会得到混乱的代码库。 - Big Daddy
我只是想提一点来支持这个答案。“MVVM 可能是过度工程化的。” 这是有道理的,特别是如果你正在使用一个框架。然而,你可以在几分钟内拼凑出 MVVM 框架的基本框架。实现一个具有 INotifyPropertyChanged 的基类和实现一个可用于执行命令的类即可。这就是构建 MVVM/WPF 应用程序所需的全部内容。 对我来说,已经到了这样的地步:对于快速测试和分析,我会选择构建 MVVM/WPF 应用程序而不是命令行应用程序。 - SomeInternetGuy

2
我一定会研究依赖注入,使用像Unity这样的框架。
您的单例类可以在依赖注入容器中注册,并注入到其他类(如ViewModels)的构造函数中。需要定期实例化并注入到类中的其他DAL类也可以这样做。
依赖注入是开发大型企业软件应用程序时最重要的设计模式,适用于客户端和服务器端代码。 MVVM是一种不错的模式,但无法解决与依赖耦合相关的整体应用程序复杂性问题。

2

这些是与MVVM相关的特定内容

1)增加了视图的“可混合性”(使用Expression Blend设计视图的能力)。这使得团队中拥有设计师和程序员的幸运者可以分别独立工作,实现责任的分离。

2)“无外观”视图逻辑。视图与其后台运行的代码无关,使得相同的视图逻辑可以在多个视图之间重复使用,或者可以轻松地重新调整或替换视图。将“行为”和“样式”分开处理。

3)没有重复的代码来更新视图。在代码后台中,你会看到到处都是“myLabel.Text = newValue”等调用。使用MVVM,只需设置底层属性及其所有视图副作用,就可以确保视图得到适当的更新。

4)可测试性。由于你的逻辑完全不涉及视图(没有“myLabel.Text”引用),因此单元测试变得非常容易。你可以测试ViewModel的行为,而不涉及其视图。这也使得使用代码后台几乎不可能进行视图行为驱动开发成为可能。

其他两种模式实际上是解决不同问题的。你可以将MVVM与MVP和MVC一起使用(大多数好的示例都会以某种形式这样做)。

实际上,在我看来,MVP(带有被动视图而不是监督控制器)只是MVVM的一个变体。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接