WPF的MVVM设计模式(从登录到增删改查Demo)

WPF的MVVM设计模式(从登录到增删改查Demo)

原文:

https://blog.csdn.net/Dear200892/article/details/101533249

什么是MVVM

MVVM即Model-View-ViewModel,通常适用于WPF或Silverlight开发。

MVC或MVP都是基于面向对象的设计模式,而MVVM是基于组件,数据驱动的设计模式。

View:使用XAML呈现给用户的界面,负责与用户交互,接收用户输入,把数据展现给用户。
Model:事物的抽象,开发过程中涉及到的事物都可以抽象为Model,例如姓名、年龄、性别、地址等属性。不包含方法,也不需要实现INotifyPropertyChanged接口。
ViewModel:负责收集需要绑定的数据和命令,聚合Model对象,通过View类的DataContext属性绑定到View,同时也可以处理一些UI逻辑。

MVVM优点

低耦合:View合一独立于Model变化和修改。一个ViewModel可以绑定到不同的"View"上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。
可重用性:你可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑。
独立开发:开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计,使用Expression Blend可以很容易设计界面并生成XAML代码。
可测试:界面素来是比较难于测试的,而现在测试可以针对ViewModel来写。

MVVM(Demo)

在这里插入图片描述
1.新建WPF项目,名称WpfMVVM。在Model中添加登录类(Login)以及用户类(User):

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

namespace WpfMVVM.Model
{
    public class Login : ICloneable
    {
        private string accountNumber;

        public string AccountNumber
        {
            get
            {
                return accountNumber;
            }

            set
            {
                accountNumber = value;
            }
        }
        private string password;

        public string Password
        {
            get
            {
                return password;
            }

            set
            {
                password = value;
            }
        }

        /// <summary>
        /// 使数据的复制变为深复制,需要实现ICloneable接口
        /// </summary>
        /// <returns></returns>
        public object Clone()
        {
            return (Object)this.MemberwiseClone();
        }


    }
}


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

namespace WpfMVVM.Model
{
    public class User :  ICloneable
    {
        private int id;
        private string name;
        private int age;
        private string sex;
        private string address;
        /// <summary>
        /// 编号
        /// </summary>
        public int ID { get { return id; } set { id = value;} }
        /// <summary>
        /// 姓名
        /// </summary>
        public string Name { get { return name; } set { name = value;} }
        /// <summary>
        /// 年龄
        /// </summary>
        public int Age { get { return age; } set { age = value; } }
        /// <summary>
        /// 性别
        /// </summary>
        public string Sex { get { return sex; } set { sex = value; } }
        /// <summary>
        /// 地址
        /// </summary>
        public string Address { get { return address; } set { address = value; } }
        /// <summary>
        /// 使数据的复制变为深复制,需要实现ICloneable接口
        /// </summary>
        /// <returns></returns>
        public object Clone()
        {
            return (Object)this.MemberwiseClone();
        }
    }
}

2.在ViewModel中创建命令绑定(DelegateCommands):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace WpfMVVM.ViewModel
{
    public class DelegateCommands : ICommand
    {
        //当命令可执行状态发生改变时,应当被激发
        public event EventHandler CanExecuteChanged;

        public Action<object> ExecuteCommand = null;

        public Func<object, bool> CanExecuteCommand = null;
        /// <summary>
        /// 用于判断命令是否可以执行
        /// </summary>
        /// <param name="parameter"></param>
        /// <returns></returns>
        public bool CanExecute(object parameter)
        {
            if (CanExecuteCommand !=null)
            {
                return CanExecuteCommand(parameter);
            }
            else
            {
                return true;
            }
        }
        /// <summary>
        /// 命令执行
        /// </summary>
        /// <param name="parameter"></param>
        public void Execute(object parameter)
        {
            if (ExecuteCommand !=null)
            {
                ExecuteCommand(parameter);
            }
        }
    }
}

实现接口ICommand。

3.在ViewModel中进行业务处理(LoginViewModel,UserViewModel):

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WpfMVVM.Model;
using WpfMVVM.View;

namespace WpfMVVM.ViewModel
{
    public class LoginViewModel : INotifyPropertyChanged
    {
        public LoginWindow log;
        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string PropertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
            }
        }

        private Login landerLogin;

        public Login LanderLogin
        {
            get
            {
                if (landerLogin == null)
                {
                    landerLogin = new Login();
                }
                return landerLogin;
            }

            set
            {
                if (landerLogin == null)
                {
                    landerLogin = new Login();
                }
                landerLogin = value;
                OnPropertyChanged("LanderLogin");
            }
        }

        public DelegateCommands LoginCommand { get; set; }

        public LoginViewModel()
        {
            LoginCommand = new DelegateCommands();
            LoginCommand.ExecuteCommand = new Action<object>(UserLogin);
        }

        public void UserLogin(object pamer)
        {
            if (LanderLogin.AccountNumber == "admin" && LanderLogin.Password == "123456")
            {
                MainWindow win = new MainWindow();
                win.ShowDialog();
            }
            else
            {
                MsgShow("用户名或密码错误");
            }
        }

        /// <summary>
        /// 显示提示信息
        /// </summary>
        /// <param name="txt"></param>
        public void MsgShow(string txt)
        {
            System.Windows.MessageBox.Show(txt);
            //删除后清空选择用户
            LanderLogin = null;
        }
    }
}

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using WpfMVVM.Model;

namespace WpfMVVM.ViewModel
{
    public class UserViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string PropertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
            }
        }

        private ObservableCollection<User> userList;
        /// <summary>
        /// 用户集合
        /// </summary>
        public ObservableCollection<User> UserList
        {
            get
            {
                if (userList == null)
                {
                    userList = new ObservableCollection<User>();
                    userList = new ShowDataViewModel().GetUsers();
                }
                return userList;               
            }
            set {
                if (userList == null)
                {
                    userList = new ObservableCollection<User>();
                }
                userList = value;
                OnPropertyChanged("UserList");
            }
        }

        public User selectUser;
        /// <summary>
        /// 被选中的用户
        /// </summary>
        public User SelectUser
        {
            get
            {
                if (selectUser == null)
                {
                    selectUser = new User();

                }
                return selectUser;
            }
            set
            {
                if (selectUser == null)
                {
                    selectUser = new User();
                }
                selectUser = value; OnPropertyChanged("SelectUser");
            }
        }
        /// <summary>
        /// 注册命令
        /// </summary>
        private void RegisterCommands()
        {
            AddCommand = new DelegateCommands();
            AddCommand.ExecuteCommand = new Action<object>(AddUser);
            UpdateCommand = new DelegateCommands();
            UpdateCommand.ExecuteCommand = new Action<object>(UpdateUser);
            DeleteCommand = new DelegateCommands();
            DeleteCommand.ExecuteCommand = new Action<object>(DeleteUser);
            SelectionCommand = new DelegateCommands();
            SelectionCommand.ExecuteCommand = new Action<object>(SelectionUser);
        }
        public UserViewModel()
        {
            RegisterCommands();
        }
        /// <summary>
        /// 显示提示信息
        /// </summary>
        /// <param name="txt"></param>
        public void MsgShow(string txt)
        {
            System.Windows.MessageBox.Show(txt);
            //删除后清空选择用户
            SelectUser = null;
        }
        #region 注册命令
        /// <summary>
        /// 新增用户
        /// </summary>
        public DelegateCommands AddCommand { get; set; }
        /// <summary>
        /// 更新用户
        /// </summary>
        public DelegateCommands UpdateCommand { get; set; }
        /// <summary>
        /// 删除用户
        /// </summary>
        public DelegateCommands DeleteCommand { get; set; }
        /// <summary>
        /// 选择用户
        /// </summary>
        public DelegateCommands SelectionCommand { get; set; }
        public void AddUser(object parameter)
        {
            //新增用户的ID为【最小】编号
            int id = 0;
            for (int i = 0; i < UserList.Count; i++)
            {
                if (UserList[i].ID != (i + 1))
                {
                    id = (i + 1);
                    break;
                }
            }
            if (id == 0)
            {
                id = UserList.Max(a => a.ID) + 1;
            }
            UserList.Insert((id - 1), new User() { ID = id, Name = SelectUser.Name, Age = SelectUser.Age, Sex = SelectUser.Sex, Address = SelectUser.Address });
            MsgShow("用户编号:" + id + "\n新增成功!");

        }
        public void UpdateUser(object parameter)
        {
            if (SelectUser.ID < 1)
            {
                MsgShow("请选择修改项!");
                return;
            }
            //查找需要修改的对象
            User user = UserList.Where(a => a.ID == SelectUser.ID).SingleOrDefault();
            //查找需要修改的对象索引
            int index = UserList.IndexOf(user);
            //使数据的复制变为深复制,需要实现ICloneable接口
            UserList[index]= (User)SelectUser.Clone();
            MsgShow("用户编号:" + SelectUser.ID + "\n修改成功!");
        }
        public void DeleteUser(object parameter)
        {
            if (SelectUser.ID < 1)
            {
                MsgShow("请选择修改项!");
                return;
            }
            User user = UserList.Where(a => a.ID == SelectUser.ID).SingleOrDefault();
            UserList.Remove(user);
            MsgShow("用户编号:" + SelectUser.ID + "\n删除成功!");
        }
        public void SelectionUser(object parameter)
        {
            DataGrid grid = (DataGrid)parameter;
            //使数据的复制变为深复制,需要实现ICloneable接口
            if (grid.SelectedItem!=null)
            {
                SelectUser = (User)((User)grid.SelectedItem).Clone();
            }           
        }
        #endregion
    }
}


注意事项:需要实现接口INotifyPropertyChanged,不然数据更新后界面无法更新。

4,在View中创建登录界面(LoginWindow.xaml) :

<Window x:Class="WpfMVVM.View.LoginWindow"
        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:WpfMVVM.View"
        mc:Ignorable="d"
        Title="Login" Height="300" Width="600">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="80"></RowDefinition>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <Label HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="30">MVVM设计模式登录</Label>

        <Label Grid.Row="1" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="40,0,0,0" FontSize="18">账号:</Label>
        <TextBox Text="{Binding LanderLogin.AccountNumber}" Grid.Row="1" Width="300" Height="30" Margin="0,0,60,0" VerticalContentAlignment="Center"></TextBox>

        <Label Grid.Row="2" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="40,0,0,0" FontSize="18" VerticalContentAlignment="Center">密码:</Label>
        <TextBox Text="{Binding LanderLogin.Password}" Grid.Row="2" Width="300" Height="30" Margin="0,0,60,0"></TextBox>

        <Button Grid.Row="3" Command="{Binding LoginCommand}">登录</Button>
    </Grid>
</Window>

cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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.Shapes;
using WpfMVVM.ViewModel;

namespace WpfMVVM.View
{
    /// <summary>
    /// Login.xaml 的交互逻辑
    /// </summary>
    public partial class LoginWindow : Window
    {
        public LoginWindow()
        {
            InitializeComponent();
            this.DataContext = new LoginViewModel();
        }
    }
}

5,在View中创建用户界面(MainWindow.xaml) ::

<Window x:Class="WpfMVVM.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:WpfMVVM.View"
        xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="450" WindowStartupLocation="CenterScreen" ResizeMode="NoResize" >
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="5*"/>
            <RowDefinition Height="3*"/>
            <RowDefinition Height="1.5*"/>
        </Grid.RowDefinitions>
        <DataGrid x:Name="dgUser" IsReadOnly="True" AutoGenerateColumns="False" CanUserAddRows="False" HorizontalAlignment="Left" ItemsSource="{Binding UserList}">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="SelectionChanged" >
                    <i:InvokeCommandAction Command="{Binding SelectionCommand}" CommandParameter="{Binding ElementName=dgUser}" />
                </i:EventTrigger>
            </i:Interaction.Triggers>
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding ID}" Header="编号"/>
                <DataGridTextColumn Binding="{Binding Name}" Header="姓名" Width="100"/>
                <DataGridTextColumn Binding="{Binding Age}" Header="年龄"/>
                <DataGridTextColumn Binding="{Binding Sex}" Header="性别" Width="60"/>
                <DataGridTextColumn Binding="{Binding Address}" Header="地址" Width="172"/>
            </DataGrid.Columns>
        </DataGrid>
        <GroupBox Header="用户基本信息" Grid.Row="1">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="*"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <StackPanel Grid.Column="0" Grid.Row="0" Orientation="Horizontal">
                    <Label x:Name="lblID" Content="编号:" VerticalAlignment="Center" />
                    <TextBox x:Name="tbxID" IsEnabled ="False"  Text="{Binding SelectUser.ID}" VerticalAlignment="Center" MaxLength="5" Height="22"  Width="90"/>
                </StackPanel>
                <StackPanel Grid.Column="1" Grid.Row="0" Orientation="Horizontal">
                    <Label x:Name="lblName"  Content="姓名:" VerticalAlignment="Center" />
                    <TextBox x:Name="tbxName" Text="{Binding SelectUser.Name}" VerticalAlignment="Center" Height="22" MaxLength="6" Width="90"/>
                </StackPanel>
                <StackPanel Grid.Column="2" Grid.Row="0" Orientation="Horizontal">
                    <Label x:Name="lblAge" Content="年龄:" VerticalAlignment="Center" />
                    <TextBox x:Name="tbxAge" Text="{Binding SelectUser.Age}" VerticalAlignment="Center" Height="22" MaxLength="4" Width="90"/>
                </StackPanel>
                <StackPanel Grid.Column="0" Grid.Row="1" Orientation="Horizontal">
                    <Label x:Name="lblSex" Content="性别:" VerticalAlignment="Center"/>
                    <ComboBox Text="{Binding SelectUser.Sex}"  SelectedIndex="0" x:Name="cbxSex" VerticalAlignment="Center"  Width="90">
                        <ComboBoxItem Tag="1" Content="男"/>
                        <ComboBoxItem Tag="2" Content="女"/>
                    </ComboBox>
                </StackPanel>
                <StackPanel  Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="2" Orientation="Horizontal">
                    <Label x:Name="lblRemarks" Content="地址:" VerticalAlignment="Center"/>
                    <TextBox x:Name="tbxRemarks" Text="{Binding SelectUser.Address}" VerticalAlignment="Center" Height="22" Width="235" />
                </StackPanel>
            </Grid>
        </GroupBox>
        <GroupBox Header="功能操作" Grid.Row="2">
            <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
                <Button x:Name="btnSave" Command="{Binding AddCommand}" Content="新增" VerticalAlignment="Center"  Width="69" Height="19" Margin="10,0,10,0" />
                <Button x:Name="btnUpdate" Command="{Binding UpdateCommand}" Content="修改" VerticalAlignment="Center" Width="69" Height="19" Margin="10,0,10,0"/>
                <Button x:Name="btnDelete" Command="{Binding DeleteCommand}" Content="删除" VerticalAlignment="Center" Width="69" Height="19" Margin="10,0,10,0"/>
            </StackPanel>
        </GroupBox>
    </Grid>
</Window>

cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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.Shapes;
using WpfMVVM.ViewModel;

namespace WpfMVVM.View
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new UserViewModel();
        }
    }
}

6,界面展示
在这里插入图片描述

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
WPF(Windows Presentation Foundation)是一个用于创建 Windows 应用程序的开发框架。MVVM(Model-View-ViewModel)是一种设计模式,用于将应用程序的业务逻辑与用户界面进行分离。 在WPF中,可以使用MVVM模式来实现增删改查功能。以下是实现增删改查的基本步骤: 1. Model(模型):模型层表示应用程序的数据源,例如从数据库或其他数据存储中检索和保存数据。可以创建一个类来定义模型,其中包含要操作的属性和方法。 2. View(视图):视图层表示用户界面,用于显示和接收用户操作。可以在XAML文件中创建视图,其中包含用户界面元素,例如按钮、文本框和数据表格。 3. ViewModel(视图模型):视图模型是模型和视图之间的中间层,用于处理业务逻辑。可以创建一个类来定义视图模型,其中包含与用户界面交互的命令和属性。视图模型还可以包含对模型的引用,用于执行增删改查操作。 4. 数据绑定:使用数据绑定将视图和视图模型连接起来。可以将视图模型的属性绑定到视图的控件,以便在用户界面上显示数据。还可以将视图模型的命令绑定到视图的按钮,以便在用户界面上触发操作。 5. 实现增删改查功能:在视图模型中编写逻辑代码,以实现增删改查功能。通过调用模型的方法,可以在数据库中执行相应的操作。然后,更新视图模型中的属性,以便在用户界面上反映出变化的数据。 通过以上步骤,就可以在WPF实现增删改查功能。MVVM模式的好处是可以将应用程序的不同功能进行清晰的分离,提高代码的可维护性和可测试性。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值