使用MVVM构建一个简单的WPF应用,本实例将使用MVVM、WPF构建一个简单计算器(如图1)。
图1 简单计算器
1、构建解决方案
首先VS中创建解决方案,并命名为:SimpleCalculator。
然后添加项目:
(1)View层:Simple.Calculator.WinForm
(2)ViewModel层:Simple.Calculator.ViewModel
(3)Model层:Simple.Calculator.Model
2、实现Model层
在Model层中创建CalculatorModel.cs(计算器实体类),并实现INotifyPropertyChanged接口。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Simple.Calculator.Model
{
/// <summary>
/// 计算器实体类
/// </summary>
public class CalculatorModel : INotifyPropertyChanged
{
private int _number1;
/// <summary>
/// 数字1
/// </summary>
public int Number1
{
get { return _number1; }
set
{
_number1 = value;
NotifyPropertyChanged("Number1");
}
}
private int _number2;
/// <summary>
/// 数字2
/// </summary>
public int Number2
{
get { return _number2; }
set
{
_number2 = value;
NotifyPropertyChanged("Number2");
}
}
private int _result;
/// <summary>
/// 计算结果
/// </summary>
public int Result
{
get { return _result; }
set
{
_result = value;
NotifyPropertyChanged("Result");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
3、实现ViewModel层
在ViewModel层中创建Common目录,并添加ViewModelBase .cs类。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Simple.Calculator.ViewModel.Common
{
public abstract class ViewModelBase : INotifyPropertyChanged
{
//属性改变事件
public event PropertyChangedEventHandler PropertyChanged;
//当属性改变的时候,调用该方法来发起一个消息,通知View中绑定了propertyName的元素做出调整
public void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
在Commom目录中,添加RelayCommand.cs类。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace Simple.Calculator.ViewModel.Common
{
public class RelayCommand : ICommand
{
#region Declarations
readonly Func<Boolean> _canExecute;
readonly Action _execute;
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="RelayCommand<T>"/> class and the command can always be executed.
/// </summary>
/// <param name="execute">The execution logic.</param>
public RelayCommand(Action execute)
: this(execute, null)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="RelayCommand<T>"/> class.
/// </summary>
/// <param name="execute">The execution logic.</param>
/// <param name="canExecute">The execution status logic.</param>
public RelayCommand(Action execute, Func<Boolean> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
#endregion
#region ICommand Members
public event EventHandler CanExecuteChanged
{
add
{
if (_canExecute != null)
CommandManager.RequerySuggested += value;
}
remove
{
if (_canExecute != null)
CommandManager.RequerySuggested -= value;
}
}
public Boolean CanExecute(Object parameter)
{
return _canExecute == null ? true : _canExecute();
}
public void Execute(Object parameter)
{
_execute();
}
#endregion
}
}
在ViewModel层中,创建CalculatorViewModel.cs(计算器ViewModel类),并继承ViewModelBase类。
using Simple.Calculator.Model;
using Simple.Calculator.ViewModel.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Simple.Calculator.ViewModel
{
/// <summary>
/// 计算器ViewModel类
/// </summary>
public class CalculatorViewModel : ViewModelBase
{
public CalculatorModel calModel = new CalculatorModel();
/// <summary>
/// 计算器实体类
/// </summary>
public CalculatorModel CalModel
{
get
{
return this.calModel;
}
set
{
this.calModel = value;
this.RaisePropertyChanged("CalModel");
}
}
/// <summary>
/// 计算命令
/// </summary>
public RelayCommand ExecuteCommand { get; set; }
/// <summary>
/// 重置命令
/// </summary>
public RelayCommand ResetCommand { get; set; }
/// <summary>
/// 初始化
/// </summary>
public CalculatorViewModel()
{
ExecuteCommand = new RelayCommand(Execute);
ResetCommand = new RelayCommand(Reset);
}
/// <summary>
/// 计算
/// </summary>
private void Execute()
{
this.CalModel.Result = this.CalModel.Number1 + this.CalModel.Number2;
}
/// <summary>
/// 重置
/// </summary>
private void Reset()
{
this.CalModel.Number1 = 0;
this.CalModel.Number2 = 0;
this.CalModel.Result = 0;
}
}
}
4、实现View层
在View层中,创建Calculator.xaml(简单计算器窗体)。
<Window x:Class="Simple.Calculator.WinForm.Calculator"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="简单计算器" Height="200" Width="400" WindowStartupLocation="CenterScreen">
<Window.Resources>
<!--文本样式-->
<Style TargetType="{x:Type Label}">
<Setter Property="HorizontalAlignment" Value="Right"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="Margin" Value="5"/>
</Style>
<!--文本框样式-->
<Style TargetType="{x:Type TextBox}" >
<Setter Property="Height" Value="40"/>
<Setter Property="Width" Value="80"/>
<Setter Property="Padding" Value="8"/>
<Setter Property="FontSize" Value="16"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="Margin" Value="0,0,0,10"/>
<Setter Property="BorderThickness" Value="1,1,1,1"/>
<Setter Property="BorderBrush" Value="DimGray"/>
</Style>
<!--按钮样式-->
<Style TargetType="{x:Type Button}">
<Setter Property="Height" Value="40"/>
<Setter Property="Width" Value="70"/>
<Setter Property="FontSize" Value="16"/>
<Setter Property="Margin" Value="20"/>
<Setter Property="Cursor" Value="Hand"/>
</Style>
</Window.Resources >
<StackPanel Margin="20" >
<StackPanel Orientation="Horizontal" Height="50" >
<TextBox Text="{Binding CalModel.Number1}" />
<Label Content="+"/>
<TextBox Text="{Binding CalModel.Number2}" />
<Label Content="="/>
<TextBox Text="{Binding CalModel.Result}" />
</StackPanel>
<StackPanel Orientation="Horizontal" >
<Button Content="计算" Command="{Binding ExecuteCommand}"/>
<Button Content="重置" Command="{Binding ResetCommand}"/>
</StackPanel>
</StackPanel>
</Window>
在Calculator.xaml.cs后台代码中,将窗体的DataContext属性设置为相应的ViewModel类。
using Simple.Calculator.ViewModel;
using System.Windows;
namespace Simple.Calculator.WinForm
{
/// <summary>
/// Calculator.xaml 的交互逻辑
/// </summary>
public partial class Calculator : Window
{
public Calculator()
{
InitializeComponent();
this.DataContext = new CalculatorViewModel();
}
}
}
最后就可以启动运行项目了。