初识MVVM

来源:互联网 发布:淘宝机器人自动回复 编辑:程序博客网 时间:2024/05/21 22:43

MVVM分解:


M->   源数据一堆get,set方法,对应Java中,JavaBean

V->    窗体,显示界面

VM-> 业务逻辑层,对窗体的逻辑响应,及数据传输的处理。


这样做的优点:

窗体改变,只需变动窗体样式,绑定对应的数据及响应事件(VM)。

VM只需处理逻辑改变

M只需添加数据或删除数据,及将数据变化反馈给UI


MVVM需要实现两个关键接口。

A)  ICommand接口,此接口用于实现界面响应事件的委托

B)  INotifyPropertyChanged接口,此接口用于实现 界面和数据源同步变化


以登录窗体为例,实现

A)修改Module中数据,改变界面显示

B)修改界面输入数据,同步Module中的数据


1)新建工程,KnowXAML

主界面类.cs如下:

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Data;

using System.Windows.Documents;

using System.Windows.Input;

using System.Windows.Media;

using System.Windows.Media.Imaging;

using System.Windows.Navigation;

using System.Windows.Shapes;

using KnowXAML.ModuleView;

 

namespace KnowXAML

{

   ///<summary>

   /// Interaction logic for MainWindow.xaml

   ///</summary>

   public partial class MainWindow :Window

    {

       public MainWindow()

        {

           InitializeComponent();

        }

    }

}

 

2新建ICommand界面命令代理类 UICommand. UICommand用于实现空间响应事件的代理。

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.Windows.Input;

 

namespace KnowXAML.DelegateCommand

{

   classUICommand :ICommand

    {

       ///<summary>

       ///判断控件是否可用

       ///</summary>

       Func<object,bool> canExecute;

 

       ///<summary>

       ///执行方法

       ///</summary>

       Action<object> executeAction;

 

       bool canExecuteCache;

       public event EventHandler CanExecuteChanged;

 

       public UICommand(Action<object> executeAction, Func<object,bool> canExecute)

        {

           this.executeAction = executeAction;

           this.canExecute = canExecute;

        }

 

        bool ICommand.CanExecute(objectparameter)

        {

           bool temp = canExecute(parameter);

           if (canExecuteCache != temp)

            {

               canExecuteCache = temp;

               if (CanExecuteChanged != null)

                   CanExecuteChanged(this,newEventArgs());

            }

           return canExecuteCache;

        }

 

       void ICommand.Execute(object parameter)

        {

           executeAction(parameter);

        }

    }

}

 

3)创建类UINotifier实现界面数据同步接口INotifyPropertyChanged此类用于同步界面和底层类(Bean)数据。

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.ComponentModel;

 

namespaceKnowXAML.DelegateNotifer

{

   public abstract class UINotifier :INotifyPropertyChanged

    {

       #region INotifyPropertyChanged

       publiceventPropertyChangedEventHandler PropertyChanged;

       #endregion

 

       #region Protected

       protectedvirtualvoid OnPropertyChanged(stringpropertyName)

        {

           if (PropertyChanged !=null)

               PropertyChanged(this,newPropertyChangedEventArgs(propertyName));

        }

       #endregion

    }

}

 

4创建底层数据类(Bean,User,继承类DelegateNotifer

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Windows;

using System.Threading.Tasks;

using KnowXAML.DelegateNotifer;

 

namespace KnowXAML.Module

{

   publicclassUser :UINotifier

    {

       privatestring userName;

       publicstring Name

        {

           get

            {

               return userName;

            }

           set

            {

               userName =value;

               OnPropertyChanged("Name");

           }           

        }

 

       privatestring userPassword;

       public string Password

        {

           get

            {

               return userPassword;

            }

           set

            {

               userPassword =value;

               OnPropertyChanged("Password");

            }

        }

    }

}

 

5)创建ModuleView类,用于User类和界面的数据桥接。

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using KnowXAML.Module;

using KnowXAML.DelegateCommand;

using KnowXAML.DelegateNotifer;

 

namespace KnowXAML.ModuleView

{

   classUserModuleView

    {

       publicUser user {get;set; }

       public UICommand uiCommand { get;set; }

 

       public UserModuleView()

        {

           this.user =newUser();

           this.uiCommand =new UICommand(SetUserInfo, arg=>true); //指定命令外//部接口uiCommand对应函数为SetUserInfouiCommand用于XMAL中配置

        }

 

       public void SetUserInfo(object parm)

        {

           user.Name ="zhangsan";

           user.Password ="123124";

        }

 

       public User userMode

        {

           get

            {

               return user;

            }

           set

            {

               if (user == value)

                   return;

               user =value;

            }

        }

 

    }

}

 

6)添加控件,修改XMAL,添加数据绑定及响应事件。黄色背景处为添加数据源,及响应事件项。

 

XMAL格式如下:

<Window x:Class="KnowXAML.MainWindow"

       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"

       xmlns:local="clr-namespace:KnowXAML"

       xmlns:vm="clr-namespace:KnowXAML.ModuleView"

       mc:Ignorable="d"

       Title="MainWindow"Height="277.407" Width="525">

   <Window.DataContext>

       <vm:UserModuleView />

   </Window.DataContext>

   <Grid>

       <Grid.ColumnDefinitions>

           <ColumnDefinition Width="118*"/>

           <ColumnDefinition Width="401*"/>

       </Grid.ColumnDefinitions>

 

       <GroupBox x:Name="groupBox"Header="GroupBox" HorizontalAlignment="Left"Margin="10,26,0,-0.4"VerticalAlignment="Top" Height="224"Width="498" Background="AliceBlue"Grid.ColumnSpan="2">

           <Grid HorizontalAlignment="Left"Margin="10,10,-3.2,34.4" Width="478">

               <Grid.ColumnDefinitions>

                   <ColumnDefinitionWidth="115*"/>

                   <ColumnDefinitionWidth="363*"/>

               </Grid.ColumnDefinitions>

               <Label x:Name="lblUserName"Content="UserName:"HorizontalAlignment="Left" Margin="31,24,0,0"VerticalAlignment="Top" Width="86"FontSize="16" Grid.ColumnSpan="2"/>

               <TextBox x:Name="txtUserName"HorizontalAlignment="Left" Height="27" Margin="20.587,29,0,0" Text="{Binding Path= userMode.Name}"TextWrapping="Wrap" VerticalAlignment="Top"Width="251" FontSize="16"Grid.Column="1"/>

               <Label x:Name="lblPassword"Content="Password:" FontSize="16" HorizontalAlignment="Left"Margin="36,82,0,0"VerticalAlignment="Top"RenderTransformOrigin="-0.205,0.338"Grid.ColumnSpan="2"/>

               <TextBox x:Name="txtPassword"HorizontalAlignment="Left" FontSize="16"Text="{Binding Path= userMode.Password}" Height="25"Margin="20.587,88,0,0"TextWrapping="Wrap" VerticalAlignment="Top"Width="251" Grid.Column="1"/>

               <Button x:Name="btnCancel"Content="Cancel"HorizontalAlignment="Left" Margin="62.587,132,0,0"VerticalAlignment="Top" Width="75"Grid.Column="1"/>

               <Button x:Name="btnOK" Command="{Binding uiCommand}" Content="OK"HorizontalAlignment="Left" Margin="196.587,132,0,0"VerticalAlignment="Top" Width="75"Grid.Column="1"/>

           </Grid>

       </GroupBox>

   </Grid>

</Window>

 

7)运行界面

初始化界面:


点击“OK”后界面

修改UserName后,点击“OK”


如果觉得我写的还不错,请关注我的微信: