学习wpf笔记3 MVVM模式——【转】C# WPF简单的MVVM模式事例

一、前言

WPF中使用MVVM模式开发有诸如以下优点:
1.结构清晰明朗,上手成本低,一个新人也能快速的定位自己需要改动代码的位置。
2.耦合度低,更改WPF控件不影响数据结构,更改代码成本低。
3.可重用性高,比如一个处理逻辑放到ViewModel模块中,其他界面如果要用掉直接调用即可。
当然并不是所有的项目都去使用MVVM开发,一些简单的我们也可以按照正常的开发。
本次例子参考“刘铁猛”老师的WPF视频教程,大家有兴趣可以去观看。
话不多说,开始写Demo。

二、需要实现目的

  1. 点击相加按钮实现数字一和数字二想加的结果:
  2. 点击保存按钮弹出文件保存窗口(只是简单的弹出窗口,并非实现正在的保存)
    在这里插入图片描述

三、编写SampleMvvmDemo

①实现思路

这是一个很简单的Demo,我们的第一反应就是,不就是一个界面上有两个Button按钮。
一个名为:“保存”,一个名为:“相加”。然后给两个Button分别添加两个Click事件。
点保存按钮的时候弹出文件保存框:

SaveFileDialog dlg = new SaveFileDialog();
dlg.ShowDialog();
 

点击相加按钮的时候计算Textbox1(数字一)与TextBox2(数字二)输入的值想加的结果然后赋值给TextBox3(结果为):

textBox3.Text = (double.Parse(textBox1.Text)+ double.Parse(textBox2.Text)).ToString();
 

其实这样没错,但是现在我把界面改变了,把保存按钮换成了保存菜单,把三个Textbox换成了三个Slider,前面两个Slider想加的结果显示到第三个Slider上面。例如这样:
在这里插入图片描述

这个时候我们就需要在后台把之前的Click事件里面的代码进行修改,随着需求的不断变更,开发成本还是比较高的,这个是我们用MVVM模式来实现一下这些效果。

②MVVM实现

首先我们创建一个SampleMvvmDemo的WPF应用项目,然后在项目中添加两个文件夹
一个为Command用来触发空间的Command
一个为ViewModels用来处理页面上的数据或者控件逻辑。
这个是项目结构,简单的MVVM框架
在这里插入图片描述
然后我们在ViewModels中添加两个类
第一个为消息通知类(NotificationObject.cs),用来告诉页面值发生了变化,需要触发逻辑

using System.ComponentModel;

namespace SampleMvvmDemo.ViewModels
{
class NotificationObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}

在这里插入图片描述
第二为窗体的交互逻辑类(MainWindowViewModel.cs),看名字也能得知这是界面与数据之间逻辑交互的地方。

using Microsoft.Win32;
using SampleMvvmDemo.Commands;
using System;

namespace SampleMvvmDemo.ViewModels
{
class MainWindowViewModel : NotificationObject
{
public MainWindowViewModel()
{
AddCommand = new DelegateCommand();
AddCommand.ExecuteAction = new Action<object>(Add);
SaveCommand = new DelegateCommand();
SaveCommand.ExecuteAction = new Action<object>(Save);
}

    private double input1;

    public double Input1
    {
        get { return input1; }
        set
        {
            input1 = value;
            RaisePropertyChanged("Input1");
        }
    }
    private double input2;

    public double Input2
    {
        get { return input2; }
        set
        {
            input2 = value;
            RaisePropertyChanged("Input2");
        }
    }
    private double resulte;

    public double Result
    {
        get { return resulte; }
        set
        {
            resulte = value;
            RaisePropertyChanged("Result");
        }
    }
    public DelegateCommand AddCommand { get; set; }
    public DelegateCommand SaveCommand { get; set; }
    private void Save(object parameter)
    {
        SaveFileDialog dlg = new SaveFileDialog();
        dlg.ShowDialog();
    }
    private void Add(object parameter)
    {
        Result = input1 + input2;
    }



}

}

 

在这里插入图片描述

写到这里的时候,会有些地方报错,这是因为我们Command还没有写方法
我们在Command文件夹中添加一个DelegateCommand.cs类,代码如下:

using System;
using System.Windows.Input;

namespace SampleMvvmDemo.Commands
{
class DelegateCommand : ICommand
{
public event EventHandler CanExecuteChanged;

    public bool CanExecute(object parameter)
    {
        if (CanExcuteFunc == null)
        {
            return true;
        }
        return CanExcuteFunc(parameter);
    }

    public void Execute(object parameter)
    {
        if (ExecuteAction == null)
        {
            return;
        }
        ExecuteAction(parameter);
    }

    public Action&lt;object&gt; ExecuteAction { get; set; }
    public Func&lt;object, bool&gt; CanExcuteFunc { get; set; }
}

}

 

在这里插入图片描述
至此,我们已经把MVVM中的VM实现了。
接下来我们把界面设计好也就是MVVM中的V。
界面代码:

<Window x:Class="SampleMvvmDemo.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:SampleMvvmDemo"
        mc:Ignorable="d"
        Title="MainWindow" Height="263" Width="300" WindowStartupLocation="CenterScreen">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Menu>
            <MenuItem Header="菜单">
                <MenuItem Header="保存" Command="{Binding SaveCommand}"/>
            </MenuItem>
        </Menu>
        <Grid Grid.Row="1">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <StackPanel Grid.Row="0" Orientation="Horizontal" >
                <TextBlock Text="数字一:" VerticalAlignment="Center"/>
                <TextBox x:Name="textBox1"  Width="242" Background="LightBlue" FontSize="24" Margin="5" Text="{Binding Input1}"/>
            </StackPanel>
            <StackPanel Grid.Row="1" Orientation="Horizontal">
                <TextBlock Text="数字二:" VerticalAlignment="Center"/>
                <TextBox x:Name="textBox2" Width="242" Background="LightBlue" FontSize="24" Margin="5" Text="{Binding Input2}"/>
            </StackPanel>
            <StackPanel Grid.Row="2" Orientation="Horizontal">
                <TextBlock Text="结果为:" VerticalAlignment="Center"/>
                <TextBox x:Name="textBox3" Width="242" Background="LightGreen" FontSize="24" Margin="5" Text="{Binding Result}"/>
            </StackPanel>
            <Button x:Name="btnAdd" Content="相加" Grid.Row="3" Width="120" Height="40" Command="{Binding AddCommand}"/>
        </Grid>
    </Grid>
</Window>
 

在这里插入图片描述

界面后台代码:

using SampleMvvmDemo.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace SampleMvvmDemo
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new MainWindowViewModel();

    }
}

}

 
 

在这里插入图片描述
我们可以看到View的后台代码非常的简洁。
即使像刚刚提到的改变控件的需求,我们也无需动后台的代码,只需要改变控件,重新绑定即可。
例如改成所说的Slider 与菜单保存

<Window x:Class="SampleMvvmDemo.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:SampleMvvmDemo"
        mc:Ignorable="d"
        Title="MainWindow" Height="263" Width="300" WindowStartupLocation="CenterScreen">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Menu>
            <MenuItem Header="菜单">
                <MenuItem Header="保存" Command="{Binding SaveCommand}"/>
            </MenuItem>
    &lt;/Menu&gt;
    &lt;Grid Grid.Row="1"&gt;
        &lt;Grid.RowDefinitions&gt;
            &lt;RowDefinition Height="Auto"/&gt;
            &lt;RowDefinition Height="Auto"/&gt;
            &lt;RowDefinition Height="Auto"/&gt;
            &lt;RowDefinition Height="*"/&gt;
        &lt;/Grid.RowDefinitions&gt;
        &lt;StackPanel Grid.Row="0" Orientation="Horizontal" &gt;
            &lt;TextBlock Text="数字一:" VerticalAlignment="Center"/&gt;
            &lt;Slider x:Name="textBox1"  Width="242" Background="LightBlue" FontSize="24" Margin="5" Value="{Binding Input1}"/&gt;
        &lt;/StackPanel&gt;
        &lt;StackPanel Grid.Row="1" Orientation="Horizontal"&gt;
            &lt;TextBlock Text="数字二:" VerticalAlignment="Center"/&gt;
            &lt;Slider x:Name="textBox2" Width="242" Background="LightBlue" FontSize="24" Margin="5" Value ="{Binding Input2}"/&gt;
            
        &lt;/StackPanel&gt;
        &lt;StackPanel Grid.Row="2" Orientation="Horizontal"&gt;
            &lt;TextBlock Text="结果为:" VerticalAlignment="Center"/&gt;
            &lt;Slider x:Name="textBox3" Width="242" Background="LightGreen" FontSize="24" Margin="5" Value="{Binding Result}"/&gt;
        &lt;/StackPanel&gt;
        &lt;Button x:Name="btnAdd" Content="相加" Grid.Row="3" Width="120" Height="40" Command="{Binding AddCommand}"/&gt;
    &lt;/Grid&gt;
&lt;/Grid&gt;

</Window>

 

在这里插入图片描述

转自https://blog.csdn.net/asd497907957/article/details/121988579?spm=1001.2101.3001.6650.14&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-14-121988579-blog-123607767.pc_relevant_multi_platform_whitelistv3&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-14-121988579-blog-123607767.pc_relevant_multi_platform_whitelistv3&utm_relevant_index=20

posted @ 2022-11-18 11:25  CastleWu  阅读(440)  评论(0编辑  收藏  举报