• 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中。

    希望大家指正。

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

  • 相关阅读:
    linux卸载mysql
    【Linux/Oracle】ORA-00031:标记要终止的会话 解决
    linux上 oracle数据库的密码过期-解决
    SYSTEM表空间满,解决方法
    Oracle 撤回已经提交的事务
    关于MySQL取不到数据
    解决mysql只能通过localhost而不能使用本机ip访问的问题
    linux 卸载php,史上最详情
    关于支付宝免密代扣申请(全),小程序,公众号,php
    mcrypt_module_open 微信小程序 php7不能使用的问题
  • 原文地址:https://www.cnblogs.com/mindflying/p/2220792.html
Copyright © 2020-2023  润新知