WPF 使用MVVM设计模式对进行增删改操作

什么是MVVM

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

MVC或MVP都是基于面向对象的设计模式,而MVVM是基于组件,数据驱动的设计模式。正是这一区别,造成大家对于MVVM学习起来比较费力。

我们可以通过下图来直观的理解MVVM设计模式:  

WPF 使用MVVM设计模式对进行增删改操作_第1张图片

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

MVVM优点

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

 MVVM简单示例

 为了让大家直观地了解MVVM的编程模式,下面会用到前面讲到的数据绑定以及命令等知识。

WPF 使用MVVM设计模式对进行增删改操作_第2张图片

1.新建WPF项目,名称WpfMVVM。在Model中添加用户类(User):

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

需要注意,后面ViewModel需要数值的复制,如果不实现ICloneable接口,那么将是浅复制,关于浅复制和深复制,请自行百度搜索,相关文章链接:https://blog.csdn.net/bigpudding24/article/details/48490145


2.在ViewModel中添加数据(ShowDataViewModel):

public class ShowDataViewModel 
{
   /// 
   /// 添加用户数据
   /// 
   /// 
   public ObservableCollection GetUsers()
   {
      ObservableCollection userList = new ObservableCollection();
      for (int i = 0; i < 15; i++)
      {
           userList.Add(new User() { ID = (i + 1), Name = "李" + (i + 1), Age = (20 + i), Sex = (i + 1) % 2 == 0 ? "女" : "男", Address = "菜园西" + (i + 1) + "号" });
      }
      return userList;
   }
}

需要注意 ,集合请不要用List关键字,不然数据更新后,View是不会刷新数据的!请使用:ObservableCollection


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

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

        public Action ExecuteCommand = null;

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

实现接口ICommand


4.在ViewModel中进行业务处理(UserViewModel):

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

        private ObservableCollection userList;
        /// 
        /// 用户集合
        /// 
        public ObservableCollection UserList
        {
            get
            {
                if (userList == null)
                {
                    userList = new ObservableCollection();
                    userList = new ShowDataViewModel().GetUsers();
                }
                return userList;               
            }
            set {
                if (userList == null)
                {
                    userList = new ObservableCollection();
                }
                userList = value;
                OnPropertyChanged("UserList");
            }
        }
        public User selectUser;
        /// 
        /// 被选中的用户
        /// 
        public User SelectUser
        {
            get
            {
                if (selectUser == null)
                {
                    selectUser = new User();

                }
                return selectUser;
            }
            set
            {
                if (selectUser == null)
                {
                    selectUser = new User();
                }
                selectUser = value; OnPropertyChanged("SelectUser");
            }
        }
        /// 
        /// 注册命令
        /// 
        private void RegisterCommands()
        {
            AddCommand = new DelegateCommands();
            AddCommand.ExecuteCommand = new Action(AddUser);
            UpdateCommand = new DelegateCommands();
            UpdateCommand.ExecuteCommand = new Action(UpdateUser);
            DeleteCommand = new DelegateCommands();
            DeleteCommand.ExecuteCommand = new Action(DeleteUser);
            SelectionCommand = new DelegateCommands();
            SelectionCommand.ExecuteCommand = new Action(SelectionUser);
        }
        public UserViewModel()
        {
            RegisterCommands();
        }
        /// 
        /// 显示提示信息
        /// 
        /// 
        public void MsgShow(string txt)
        {
            System.Windows.MessageBox.Show(txt);
            //删除后清空选择用户
            SelectUser = null;
        }
        #region 注册命令
        /// 
        /// 新增用户
        /// 
        public DelegateCommands AddCommand { get; set; }
        /// 
        /// 更新用户
        /// 
        public DelegateCommands UpdateCommand { get; set; }
        /// 
        /// 删除用户
        /// 
        public DelegateCommands DeleteCommand { get; set; }
        /// 
        /// 选择用户
        /// 
        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,不然数据更新后界面无法更新。

                  对于引用类型的值之间复制,是需要使用深复制,不然改动其中一个值,另一个值同时也会变更,使用方法:                             SelectUser = (User)((User)grid.SelectedItem).Clone();     

关于AddUser方法,我为何不直接让ID去集合的最大值呢?因为几天前我在论坛看到一个帖子,按照他说的内容,特意这么做,请不要模仿!!!


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


    
        
            
            
            
        
        
            
                
                    
                
            
            
                
                
                
                
                
            
        
        
            
                
                    
                    
                    
                
                
                    
                    
                
                
                    
                
                    
                
                    
                
                    
                
                    
            
        
        
            
                

 如果你想点击表格内容,就能够在下方的用户基本信息刷新数据,那么你就需要引用:xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity",如果没有这个dll,请在【工具=》Nuget包管理器=》管理解决方案的Nuget程序包】中搜索System.Windows.Interactivity,选择【System.Windows.Interactivity.WPF】即可!

WPF 使用MVVM设计模式对进行增删改操作_第3张图片

cs:

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

 


6.运行效果图:        

WPF 使用MVVM设计模式对进行增删改操作_第4张图片 运行图 WPF 使用MVVM设计模式对进行增删改操作_第5张图片 选择用户 WPF 使用MVVM设计模式对进行增删改操作_第6张图片 修改信息 WPF 使用MVVM设计模式对进行增删改操作_第7张图片 删除用户 WPF 使用MVVM设计模式对进行增删改操作_第8张图片 新增用户

若你们二位不幸看到我举例用户,找到我再说~~~~


7.项目源码:

百度网盘链接:https://pan.baidu.com/s/1fxsZAtfFURIJi-g2kqunjw 提取码:2zy4 
             CSDN下载: https://download.csdn.net/download/dear200892/11827306

你可能感兴趣的:(C#,#,WPF)