您的位置:首页 > 其它

初识MVVM

2017-09-22 10:34 134 查看
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
{
   
class
UICommand :
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;
 
namespace
KnowXAML.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
{
   
public
class
User :
UINotifier
    {
       
private
string userName;
       
public
string Name
        {
           
get
            {
               return
userName;
            }
           
set
            {
               userName =
value;
               OnPropertyChanged("Name");
           }           

        }
 
       
private
string 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
{
   
class
UserModuleView
    {
       
public
User user {
get;
set; }
       
public UICommand
uiCommand { get;
set; }

 
       
public UserModuleView()
        {
           
this.user =
newUser();
           
this.uiCommand =
new UICommand(SetUserInfo,
arg=>true); //指定命令外//部接口uiCommand对应函数为SetUserInfo。uiCommand用于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”



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

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: