Prism学习笔记(二)简单的MVVM模式

 

现在我们进入Prism的一条重要支柱MVVM模式。MVVM模式简单来说就是把页面UI和后台逻辑分开,这样做的好处是能使你的程序更容易测试,维护和改进。下面的图来自于Prism4的教程显示了MVVM模式的基本工作原理:

好,废话少说,开始Coding吧。

打开之前创建的MyPrism程序:

其中HelloWorldModule下只有一个View页面HelloWorldView.xaml,其只实现一个简单显示HelloWorld控件作用,不包括任何逻辑代码。

为了实现MVVM模式,我们需要添加一个ViewModel文件和Model文件。

在Helloworldmodule下新建两个文件夹,命名为Models和ViewModels,分别添加一个cs文件,如下图:

接下来,修改HellowWorldView页面,实现一个简单的加法界面

 代码如下:

<UserControl x:Class="HelloWorldModule.Views.HelloWorldView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    xmlns:ds="clr-namespace:HelloWorldModule.ViewModels"
    d:DesignHeight="429" d:DesignWidth="618" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk">

    <UserControl.DataContext>
        <ds:HelloWorldViewModel/>
    </UserControl.DataContext>
    
    <Grid x:Name="LayoutRoot" Background="White">
        <Grid.RowDefinitions>
            <RowDefinition Height="63"/>
            <RowDefinition Height="40"/>
            <RowDefinition Height="50"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="150"/>
            <ColumnDefinition Width="50"/>
            <ColumnDefinition Width="150"/>
            <ColumnDefinition Width="50"/>
            <ColumnDefinition Width="150"/>  
        </Grid.ColumnDefinitions>        
        
        <TextBlock Grid.ColumnSpan="5" Text="Hello World" Foreground="Green" HorizontalAlignment="Center" VerticalAlignment="Center" FontFamily="Calibri" FontSize="24" FontWeight="Bold"></TextBlock>
        <TextBox Grid.Row="1" Grid.Column="0"  Height="23"  Name="Number1" Text="{Binding HelloWorldModel.Number1, Mode=TwoWay}" Width="120"/>
        <TextBox Grid.Row="1"  Grid.Column="2" Height="23"  Name="Number2" Text="{Binding HelloWorldModel.Number2, Mode=TwoWay}" Width="120"/>
        <sdk:Label Grid.Row="1"  Grid.Column="4" Height="28" Name="Result" Content="{Binding HelloWorldModel.Result, Mode=TwoWay}" Width="120"/>
        <sdk:Label Grid.Row="1"  Grid.Column="1" Height="23" Name="label1" Content="+" Width="30"/>
        <sdk:Label Grid.Row="1"  Grid.Column="3" Height="22" Name="label2" Content="=" Width="30"/>
        <Button Content="Add" Grid.Row="2"  Grid.Column="4" Command="{Binding AddCommand}" Height="25"  Name="btnAdd" Width="75"/>

    </Grid>
</UserControl>




其中的关键代码:

xmlns:ds="clr-namespace:HelloWorldModule.ViewModels"

<UserControl.DataContext>
     <ds:HelloWorldViewModel/>
</UserControl.DataContext>


这里吧HellowWorldViewModel类所为HellowWorldView的DataContext,也就是说View中的所有数据绑定都在HellowWorldViewModel类中定义。

<TextBox Grid.Row="1" Grid.Column="0"  Height="23"  Name="Number1" Text="{Binding HelloWorldModel.Number1, Mode=TwoWay}" Width="120"/>
<TextBox Grid.Row="1"  Grid.Column="2" Height="23"  Name="Number2" Text="{Binding HelloWorldModel.Number2, Mode=TwoWay}" Width="120"/>
<sdk:Label Grid.Row="1"  Grid.Column="4" Height="28" Name="Result" Content="{Binding HelloWorldModel.Result, Mode=TwoWay}" Width="120"/>

这三个控件中,Text绑定了HelloWorldModel.Number1属性,并且是双向绑定,双向绑定既是,如果程序既可以将HelloWorldModel.Number1属性绑定到页面,也可以从页面得到数据。如将其改为单向绑定,程序就无法读取客户输入的数字了。

 

<Button Content="Add" Grid.Row="2"  Grid.Column="4" Command="{Binding AddCommand}" Height="25"  Name="btnAdd" Width="75"/>

此处将Button绑定到我们自定义的AddCommand中。

好接下来我们就要在HellowWorldViewModel类中实现Number1,Number2,Result这个三个绑定参数和AddCommand命令。

下面是HellowWorldModel类代码

using System.ComponentModel;

namespace HelloWorldModule.Models
{
    public class HelloWorldModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public int Number1 { get; set; }

        public int Number2 { get; set; }

        private int result;

        public int Result
        {
            get
            {
                return this.result; 
            }

            set
            {
                if (value != this.result)
                {
                    this.result = value;
                    if (this.PropertyChanged != null)
                    {
                        this.PropertyChanged(this, new PropertyChangedEventArgs("Result"));
                    }
                }
            }
        }
         
    }
}


在HellowWorldModel类中我们定义了基本的参数属性Number1,Number2,Result。Number1,Number2较为简单。Result中包含了一个PropertyChanged的事件,该事件的作用简单来说就是,一旦Result值发生了变化,他将通知所有的绑定Result的控件,刷新数据。为了实现该事件,该类必须继承INotifyPropertyChanged。具体的原理这里就不多说了,网上多的是。

HellowWorldViewModel类代码

using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Windows.Input;
using Microsoft.Practices.Prism.Commands;
using HelloWorldModule.Models;

namespace HelloWorldModule.ViewModels
{
    public class HelloWorldViewModel
    {
        private readonly HelloWorldModel  helloWorldModel;

        public HelloWorldViewModel()
        {
            this.helloWorldModel = new HelloWorldModel();           
            this.AddCommand = new DelegateCommand<object>(this.OnSubmit);
        }

        public HelloWorldModel HelloWorldModel
        {
            get { return this.helloWorldModel; }
        }

        public ICommand AddCommand { get; private set; }

        private void OnSubmit(object obj)
        {
            helloWorldModel.Result = helloWorldModel.Number1 + helloWorldModel.Number2;
        }

   
    }
}

HellowWorldViewModel中创建了一个HellowWorldModel的实例,同时创建AddCommand方法,并实现其具体操作OnSubmit,这些都用来绑定到HellowWorldView中。

OnSubmit中将Number1和Number2的数据相加赋给了Result,由于属性Result实现了PropertyChanged事件,其值一发生变化,便刷新了Result控件值。

好所有的代码都完成了,按F5键运行,得到以下结果。

这篇文章主要是谈了MVVM模式的基本架构和功能实现。关键就在于数据绑定和PropertyChanged事件。

另外读者可能会有疑惑为什么要把HellowWorldModel类和HellowWorldViewModel类分开写,其实完全可以把两者和为一个类。Prism官方给出的ViewModel和Model的区别是:

ViewModel:The view model in the MVVM pattern encapsulates the presentation logic and data for the view. Viewmodel封装了展现的逻辑和数据。

Model:The model in the MVVM pattern encapsulates business logic and data. Model封装了业务的逻辑和数据。

笔者里的理解是分开是为了使代码更清晰,便于阅读。像页面操作如本例中的数据相加操作属于页面的逻辑,因此放在HellowWorldViewModel中,如果有数据库读取或者和其他模块交互,那就属于业务逻辑,就应该放在HellowWorldModel中。

希望大家指正。

源代码:http://files.cnblogs.com/mindflying/MyPrism_BasicMVVM.zip

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值