参考学习:https://www.bilibili.com/video/BV1LW41197LV?from=search&seid=12286516498324341778&spm_id_from=333.337.0.0
一,MVVM模式:表现层的UI框架
二,Winform和WPF开发思维的区别
Winform:开发思维点:界面
MVVM模式开发 :Model,数据驱动
三,MVVM的理解
Model:对象的抽象结果
View:只是布局,通过DataContext(上下文)来绑定对应的ViewModel。
ViewModel:连接View和Model,借助Command来负责界面的跳转和调用Model中方法来操作Model的数据。
数据对应着ViewMode中的Property,执行的命令对应着ViewModel中的Command。
ViewModel与View的沟通:
传递数据--数据属性
传递操作--命令属性
Binding:如果某个对象的某个属性 借助 DataBinging 关联在了界面上的某个元素上面,当属性值变化的时候,实际上Binding就是在侦听着PropertyChangedEventHandler这个事件,一旦这个事件发生了,就把属性变化后的值送到界面上。
四,数据绑定
数据绑定要达到的效果:
【1】界面View修改,Model自动更新
【2】Model修改,界面View自动更新
五,项目演示:旧的winform方式做项目
【5.1】第一次需求
1,功能要求:
功能1:点击Add按钮,计算2个文本框的数值相加。
功能2:点击Save按钮,保存到一个文件。
2,根据客户需求写界面代码:
<Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="*"></RowDefinition> </Grid.RowDefinitions> <Button x:Name="Save" Content="Save" Click="Save_OnClick"></Button> <Grid Grid.Row="1"> <Grid.ColumnDefinitions> <ColumnDefinition Width="22*"/> <ColumnDefinition Width="169*"/> <ColumnDefinition Width="326*"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="*"></RowDefinition> </Grid.RowDefinitions> <TextBox x:Name="tb1" Grid.Row="0" Background="LightBlue" FontSize="24" Margin="4" Grid.ColumnSpan="3"></TextBox> <TextBox x:Name="tb2" Grid.Row="1" Background="LightBlue" FontSize="24" Margin="4" Grid.ColumnSpan="3"></TextBox> <TextBox x:Name="tb3" Grid.Row="2" Background="LightBlue" FontSize="24" Margin="4" Grid.ColumnSpan="3"></TextBox> <Button x:Name="addButton" Grid.Row="3" Content="Add" Width="120" Height="80" Click="AddButton_OnClick" Grid.Column="2" Margin="7,50,199,50"></Button> </Grid> </Grid>
3,根据客户需求写逻辑代码:
private void AddButton_OnClick(object sender, RoutedEventArgs e) { double d1 = double.Parse(this.tb1.Text); double d2 = double.Parse(this.tb2.Text); double result = d1 + d2; this.tb3.Text = result.ToString(); } private void Save_OnClick(object sender, RoutedEventArgs e) { SaveFileDialog dlg=new SaveFileDialog(); dlg.ShowDialog(); }
【5.2】客户要改需求了,第二次需求
1,客户要界面,更改需求:
功能1:点击Add按钮,计算2个文本框的数值相加。
功能1改为:通过拉进度条的方式代替文本框的方式。
功能2:点击Save按钮,保存到一个文件。
功能2改为:通过菜单方式保存
2,通过新需求更改界面
<Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="*"></RowDefinition> </Grid.RowDefinitions> <Menu> <MenuItem Header="File"> <MenuItem Header="Save" x:Name="saveMenuItem" Click="SaveMenuItem_OnClick"></MenuItem> </MenuItem> </Menu> <Grid Grid.Row="1"> <Grid.RowDefinitions> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="*"></RowDefinition> </Grid.RowDefinitions> <Slider x:Name="slider1" Grid.Row="0" Background="LightBlue" Minimum="0" Maximum="100" Margin="4" ></Slider> <Slider x:Name="slider2" Grid.Row="1" Background="LightBlue" Minimum="0" Maximum="100" Margin="4" ></Slider> <Slider x:Name="slider3" Grid.Row="2" Background="LightBlue" Minimum="0" Maximum="100" Margin="4" ></Slider> <Button x:Name="addButton2" Grid.Row="3" Content="Add" Width="120" Height="80" Click="AddButton_OnClick2" Grid.Column="2"></Button> </Grid> </Grid>
3,通过新需求,更改逻辑
注意:这是控件名称变了,之前写好的都报错了,要把之前的代码全部都删除,全部重新写逻辑
新需求的逻辑代码:
private void AddButton_OnClick2(object sender, RoutedEventArgs e) { this.slider3.Value = this.slider1.Value + this.slider2.Value; } private void SaveMenuItem_OnClick(object sender, RoutedEventArgs e) { SaveFileDialog dlg = new SaveFileDialog(); dlg.ShowDialog(); }
【5.3】如果后期客户又要改界面,逻辑代码又要重新删除,重新编写,到时候项目大了,会非常的耗损时间精力。
六,MVVM模式演示上面的功能修改
【6.1】准备工作
1,
namespace WPF_MVVM设计模式.ViewModels { /// <summary> /// 自定义的一个ViewModel的基类 /// </summary> class NotificationObject : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; public void RaisePropertyChanged(string proPertyName) { if (this.PropertyChanged != null) { this.PropertyChanged.Invoke(this,new PropertyChangedEventArgs(proPertyName));//参数:proPertyName,告诉Binding是哪个属性值发生改变了 } } } }
2,
namespace WPF_MVVM设计模式.Commands { class DelegateCommand : ICommand { /// <summary> /// 当命令能不能执行的这个状态发生改变的时候,你有机会通知一下命令的调用者,告诉他状态 /// </summary> public event EventHandler CanExecuteChanged; /// <summary> /// 帮助命令的呼叫者来判断这个命令能不能执行 /// </summary> /// <param name="parameter"></param> /// <returns></returns> public bool CanExecute(object parameter) { if (this.CanExecuteFunc == null) { return true; } return this.CanExecuteFunc(parameter); } /// <summary> /// 当命令执行的时候,你想做什么事情 /// </summary> /// <param name="parameter"></param> public void Execute(object parameter) { if (this.ExecuteAction == null) { return; } this.ExecuteAction(parameter); } public Action<object> ExecuteAction { get; set; } public Func<object,bool> CanExecuteFunc { get; set; } } }
【6.2】分析:
1,数据属性:3个值
2,命令属性:保存按钮和计算按钮
namespace WPF_MVVM设计模式.ViewModels { class MainWindowViewModel:NotificationObject { #region 数据属性 private double input1; public double Input1 { get { return input1; } set { input1 = value; this.RaisePropertyChanged("Input1"); } } private double input2; public double Input2 { get { return input2; } set { input2 = value; this.RaisePropertyChanged("Input2"); } } private double result; public double Result { get { return result; } set { result = value; this.RaisePropertyChanged("Result"); } } #endregion #region 命令属性 public DelegateCommand AddCommand { get; set; } public DelegateCommand SaveCommand { get; set; } private void Add(object parameter) { this.Result = this.Input1 + this.Input2; } private void Save(object parameter) { SaveFileDialog dlg=new SaveFileDialog(); dlg.ShowDialog(); } public MainWindowViewModel() { this.AddCommand=new DelegateCommand(); this.AddCommand.ExecuteAction=new Action<object>(this.Add); this.SaveCommand=new DelegateCommand(); this.SaveCommand.ExecuteAction=new Action<object>(this.Save); } #endregion } }
【6.3】第一次需求
界面:
<Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="*"></RowDefinition> </Grid.RowDefinitions> <Button x:Name="Save" Content="Save" Command="{Binding SaveCommand}" ></Button> <Grid Grid.Row="1"> <Grid.ColumnDefinitions> <ColumnDefinition Width="22*"/> <ColumnDefinition Width="169*"/> <ColumnDefinition Width="326*"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="*"></RowDefinition> </Grid.RowDefinitions> <TextBox x:Name="tb1" Grid.Row="0" Background="LightBlue" FontSize="24" Margin="4" Grid.ColumnSpan="3" Text="{Binding Input1}"></TextBox> <TextBox x:Name="tb2" Grid.Row="1" Background="LightBlue" FontSize="24" Margin="4" Grid.ColumnSpan="3" Text="{Binding Input2}"></TextBox> <TextBox x:Name="tb3" Grid.Row="2" Background="LightBlue" FontSize="24" Margin="4" Grid.ColumnSpan="3" Text="{Binding Result}"></TextBox> <Button x:Name="addButton" Grid.Row="3" Content="Add" Width="120" Height="80" Grid.Column="2" Margin="7,50,199,50" Command="{Binding AddCommand}"></Button> </Grid> </Grid>
【6.4】MVVM更改第二次需求:
只用改界面,Binding数据属性和命令属性就可以了,逻辑完全不用动了。
<Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="*"></RowDefinition> </Grid.RowDefinitions> <Menu> <MenuItem Header="File"> <MenuItem Header="Save" x:Name="saveMenuItem" Command="{Binding SaveCommand}"></MenuItem> </MenuItem> </Menu> <Grid Grid.Row="1"> <Grid.RowDefinitions> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="*"></RowDefinition> </Grid.RowDefinitions> <Slider x:Name="slider1" Grid.Row="0" Background="LightBlue" Minimum="0" Maximum="100" Margin="4" Value="{Binding Input1}" ></Slider> <Slider x:Name="slider2" Grid.Row="1" Background="LightBlue" Minimum="0" Maximum="100" Margin="4" Value="{Binding Input2}" ></Slider> <Slider x:Name="slider3" Grid.Row="2" Background="LightBlue" Minimum="0" Maximum="100" Margin="4" Value="{Binding Result}" ></Slider> <Button x:Name="addButton2" Grid.Row="3" Content="Add" Width="120" Height="80" Grid.Column="2" Command="{Binding AddCommand}"></Button> </Grid> </Grid>