• WPF-MVVM模式-表现层的UI框架【学习笔记】


    参考学习: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>
    

      

  • 相关阅读:
    Jenkins配置基于角色的项目权限管理--转
    linux下ssh/scp无密钥登陆方法
    Jenkins+Maven+Git CI环境搭建手册
    Linux操作系统下的Sudo命令
    使用secureCRT远程Linux,出现远程主机拒绝连接
    解决SecureCRT连接linux超时后断开
    使用git整体流程
    JAVA Map集合类简介
    几个经常用到的字符串的截取(java)
    maven
  • 原文地址:https://www.cnblogs.com/baozi789654/p/15411947.html
Copyright © 2020-2023  润新知