WPF MVVM模式构建项目
什么是MVVM模式?
MVVM是Model-View-ViewModel的简写,Model就是模型,View就是视图,ViewModel就是View和Model之间解耦和传递消息的中间层。MVVM采用双向数据绑定,View中数据变化将自动反映到ViewModel上,反之,Model中数据变化也将会自动展示在View上。通过MVVM模式使得View和Model上的修改相互不影响,方便程序分工,测试和维护。
基于WPF的MVVM模式的框架有很多种,流行的是MvvmLight(轻量级Mvvm框架,现已不更新)和Prism(大型Mvvm框架),本篇不使用框架来实现MVVM模式构建项目,了解WPF内部实现机理。使用MVVM框架请参考:
MvvmLight:WPF MVVMLight介绍和使用(1)_无熵~的博客-CSDN博客
Prism:WPF Prism介绍和简单实例_prism.wpf_无熵~的博客-CSDN博客
创建一个基于MVVM模式的登录项目,实现方式:
首先建立相应的文件夹:一个ViewModel,一个View,一个Model。在ViewModel里面有一个基础的通知类:NotifyPropertyChanged,这个类继承自INotifyPropertyChanged(这个类是通知的基础类,当事件执行时,会将相应的值显示在绑定的控件上);一个命令通知类:DelegateCommand,实现ICommand接口,用于消息传递。
Model类:如果想让属性绑定到其他数据,可以将属性定义成依赖属性并让类继承DependencyObject类。
public class User:DependencyObject{public string Name{get { return (string)GetValue(NameProperty); }set { SetValue(NameProperty, value); }}// Using a DependencyProperty as the backing store for Name. This enables animation, styling, binding, etc...public static readonly DependencyProperty NameProperty =DependencyProperty.Register("Name", typeof(string), typeof(User), new PropertyMetadata(null));public string Password{get { return (string)GetValue(PasswordProperty); }set { SetValue(PasswordProperty, value); }}public static readonly DependencyProperty PasswordProperty =DependencyProperty.Register("Password", typeof(string), typeof(User), new PropertyMetadata(null));}
View页面实现:
<Window x:Class="WpfMvvmDemo.View.LoginWindow"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:WpfMvvmDemo.View"mc:Ignorable="d"Title="{Binding Info}" Height="450" Width="800" WindowStartupLocation="CenterScreen"><Grid><Grid.RowDefinitions><RowDefinition/><RowDefinition/><RowDefinition/></Grid.RowDefinitions><TextBox x:Name="txtUser" Text="{Binding User.Name,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" VerticalContentAlignment="Center" HorizontalContentAlignment="Center"Width="300" Height="40"/><TextBox x:Name="txtPassword" Text="{Binding User.Password,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" VerticalContentAlignment="Center" HorizontalContentAlignment="Center"Grid.Row="1" Width="300" Height="40" /><Button Content="Query" Command="{Binding LoginCommand}" CommandParameter="login"Grid.Row="2" Width="200" Height="30" /></Grid>
</Window>
View页面指定数据源:
/// <summary>/// LoginWindow.xaml 的交互逻辑/// </summary>public partial class LoginWindow : Window{public LoginWindow(){InitializeComponent();this.DataContext = new UserVM();}}
ViewModel类:
public class UserVM: NotifyPropertyChanged{private string info;public string Info{get { return info; }set{info = value;OnPropertyChanged();}}public UserVM(){User = new User(){Name = "admin",Password = "123456"};Info = "用户登录";}private User user;public User User{get { return user; }set{user = value;OnPropertyChanged();//NotifyPropertyChanged("User");}}public ICommand LoginCommand{get { return new DelegateCommand(LoginCommandEvent, CanLogin); }}private void LoginCommandEvent(Object o){MessageBox.Show(string.Format($"用户:{User.Name},参数:{o.ToString()}"));}private bool CanLogin(Object o){if(o!=null){return true;}return false;}}
ViewModel中NotifyPropertyChanged类定义,继承自INotifyPropertyChanged。
public class NotifyPropertyChanged : INotifyPropertyChanged{/// <summary>/// 实现接口/// </summary>public event PropertyChangedEventHandler PropertyChanged;/// <summary>/// 属性变更事件/// </summary>/// <param name="Path">事件源</param>public void OnPropertyChanged([CallerMemberName] string propertyName = ""){this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));}}
ViewModel中DelegateCommand类定义,实现ICommand接口。
public class DelegateCommand : ICommand{public event EventHandler CanExecuteChanged{add{if (_canExecute != null){CommandManager.RequerySuggested += value;}}remove{if (_canExecute != null){CommandManager.RequerySuggested -= value;}}}public bool CanExecute(object parameter){if (_canExecute == null){return true;}return _canExecute(parameter);}public void Execute(object parameter){if (_execute != null && CanExecute(parameter)){_execute(parameter);}}private Func<object, bool> _canExecute;private Action<object> _execute;public DelegateCommand(Action<object> execute, Func<object, bool> canExecute){_execute = execute;_canExecute = canExecute;}public DelegateCommand(Action<object> execute) :this(execute, null){}}
实例链接:https://download.csdn.net/download/lvxingzhe3/87669239