一、WPF MVVM 开发核心模式

1、MVVM模式介绍说明【Mdeols-View-ViewModel】
1、什么是MVVM ?
MVVM是一种设计模式、开发经验。
2、MVVM背景与开发模式的升级
微软公司提出的这种设计模式,基于控件。
3、MVVM模式下的应用分层
视图【View】:可视化界面 widow ;Page;UserControl
模型【Models】:存放数据模型 类文件 存放的内容:界面中的对象属性
视图模型【ViewModels】:业务逻辑 类文件
要求:代码\项目结构,严格来说,在开发当中有一个标准的项目结构。
2、MVVM模式下的数据处理
1、数据绑定
依赖属性必须继承DependencyObject
静态属性:属性名称+Changed事件 固定写法
数据模型类:INotifyPropertyChanged 接口:形成一种契约 【当属性值发生变化后,进行通知】

新建View类:MainWindow

<Window x:Class="WpfApp16.View.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:WpfApp16"
xmlns:vm="clr-namespace:WpfApp16.ViewModel"
mc:Ignorable="d" FontSize="20"
Title="主界面" Height="450" Width="800">
<Window.DataContext>
<vm:MainWindowViewModel></vm:MainWindowViewModel>
</Window.DataContext>
<Grid>
<StackPanel>
<TextBox Text="{Binding mwm.Value}"></TextBox>
<Slider Minimum="0" Maximum="100" Value="{Binding mwm.Value1}"></Slider>
<TextBox Text="{Binding mwm.Value2}"></TextBox>
</StackPanel>
</Grid>
</Window>

新建Model类:MainWindowModel

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WpfApp16.MainWindowViewModel
{
public class MainWindowModel: INotifyPropertyChanged
{
public double Value { get; set; } = 123;
public double Value1 { get; set; } = 23;
private double value2;

public double Value2
{
get { return value2; }
set {
value2 = value;
PropertyChanged.Invoke(this, new PropertyChangedEventArgs("value2"));
}
}
public event PropertyChangedEventHandler? PropertyChanged;//订阅这个实例中对象需要更新了
}
}

新建ViewModel类:MainWindowViewModel

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WpfApp16.Model;

namespace WpfApp16.ViewModel
{
public class MainWindowViewModel
{


public MainWindowModel mwm { get;set; } =new MainWindowModel();
/// <summary>
///数值相加
/// </summary>
public void Add()
{
mwm.Value2 = mwm.Value + mwm.Value1;
}
public MainWindowViewModel()
{
Task.Factory.StartNew(() => {
Task.Delay(2000).Wait();
Add();
});

}
}
}
2、基于Model的数据验证
参照绑定表达式
3、数据模型类的辅助插件
从 nuget上获取:PropertyChanged.Fody
实现原理:在编译的时候,再属性中实现INotifyPropertyChanged 相关代码
3、MVVM模式下的基本行为处理
1、什么是命令
特定指令、有明确的执行内容,带有一定的强制性。
参照事件,但与事件不同。
2、命令的用途
A:第一个目的是将语义和调用命令的对象与执行命令逻辑分开。
这允许多个和不同的源调用相同的命令逻辑,并允许针对不同的目标定义命令逻辑。
B:命令的另一个用途是统一的指示操作是否可用。

基本语法:
新建类 BaseCommand:继承:ICommand接口

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Input;

namespace WpfApp3
{
public class BaseCommand : ICommand
{
/// <summary>
/// 通知 当前按钮检查可用条件
/// </summary>
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
/// <summary>
///通过返回值确定绑定当前命令实例的对象是否可用
/// </summary>
/// <param name="parameter"></param>
/// <returns></returns>
public bool CanExecute(object parameter)
{
return doCanExecute?.Invoke(parameter)==true;
}
/// <summary>
/// 执行过程
/// </summary>
/// <param name="parameter"></param>
public void Execute(object parameter)
{
doExecute?.Invoke(parameter);
}
/// <summary>
/// 执行过程委托
/// </summary>
public Action<object> doExecute { get; set; }
/// <summary>
///
/// </summary>
public Func<object, bool> doCanExecute { get; set; }
}
}

新建类:MainModel 继承:INotifyPropertyChanged

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Windows.Input;

namespace WpfApp3.Model
{
public class MainModel : INotifyPropertyChanged
{
private string _value = "小明";

public string Value
{
get { return _value; }
set
{
_value = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Value"));
//CommandManager.InvalidateRequerySuggested();//可省略
}
}
private string _value1="小刚";

public string Value1
{
get { return _value1; }
set { _value1 = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Value1"));
//CommandManager.InvalidateRequerySuggested();//可省略
}
}


public BaseCommand btnCom { get; set; }
public BaseCommand btnCom1 { get; set; }
public MainModel()
{
btnCom = new BaseCommand()
{
doExecute = new Action<object>(Hellow),
doCanExecute = new Func<object, bool>(CanHellow)

};
btnCom1 = new BaseCommand()
{
doExecute = new Action<object>(Word),
doCanExecute = new Func<object, bool>(CanWord)
};
}

public event PropertyChangedEventHandler PropertyChanged;

public void Hellow(object o)
{
Value = "Hellow";
}
public bool CanHellow(object o)
{
if (Value == "Hellow") return false;
return true;
}
public bool CanWord(object o)
{
if (Value1 == "Word") return false;
return true;
}
public void Word(object o)
{
Value1 = "Word";
}
}
}

新建类MainViewModel:

using System;
using System.Collections.Generic;
using System.Text;
using WpfApp3.Model;

namespace WpfApp3.ViewModel
{
public class MainViewModel
{
public MainModel model { get; set; } = new MainModel ();
}
}

xaml代码如下:

<Window x:Class="WpfApp3.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:WpfApp3"
xmlns:mvm="clr-namespace:WpfApp3.ViewModel"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.DataContext>
<mvm:MainViewModel></mvm:MainViewModel>
</Window.DataContext>
<Grid>
<StackPanel>
<TextBox Text="{Binding model.Value}"></TextBox>
<Button Command="{Binding model.btnCom}" CommandParameter="123" Height="30" Content="Say Hellow"></Button>
<TextBox Text="{Binding model.Value1}"></TextBox>
<Button Command="{Binding model.btnCom1}" CommandParameter="123" Height="30" Content="Say Word"></Button>
</StackPanel>
</Grid>
</Window>
4、MVVM模式下的任意事件处理
ICommand
1、自定义命令ICommand接口
是否可执行方法:CanExecute
主要执行逻辑:Execute
触发检查是否可执行:CanExecuteChanged
2、命令参数传递
<Button Command="{Binding model.btnCom1}" CommandParameter="123" Height="30" Content="Say Word"></Button>
3、预定义与内置命令
MediaCommands (24个):Paly Stop Pause ......
ApplicationCommands(23个):New Open Copy Cut Print.....
NavigationCommands(16个):GoToPage LastPage Favorites .....
ComponentCommands(27个):ScrollByLine MoveDown ExtendSelectionDown.....
EditingCommands(54个):Delete ToggleUnderline ToggleBold.....
4、路由命令【了解】
CommandBings/RouteCommand/RouteUICommand
InputBindings /事件绑定
1、鼠标输入的命令绑定

InputBindings:

<MouseBing  MouseAction ="RightClick" Command="{Bind TreeItemClickCommand}" />

单击鼠标左键:LeftClick 双击鼠标左键:LeftDoubleClick
单击鼠标中键:ModdleClick 双击鼠标中键:ModdleDoubleClick
单击鼠标右键:RightClick 双击鼠标右键:RightDoubleClick
2、任意事件绑定:System.Windows.Interactivity