Thursday, April 5, 2018

Refactor an MVVM ViewModel Class

Good afternoon!
I recently asked the forums on how to refactor a ViewModel class given that in the future additional features or functionalities will be added, so the ViewModel class becomes bloated and hard to trace. All the commands, database operations and properties are declared in this class. So, the option I was thinking was segregation but I also need inputs from other experienced developers in the community.
Sample ViewModel Class
namespace MVVM.MainApplication.ViewModel
{
   public class EmployeeViewModel : ViewModelBase
  {        
        private ICommand _saveCommand;
        private ICommand _resetCommand;
        private ICommand _editCommand;
        private ICommand _deleteCommand;
        private Employee _employeeEntity;
        private EmployeeRepository _repository;
 
        private EmployeeModel _employeeModel;
        public EmployeeModel EmployeeModel
        {
            get
            {
                return _employeeModel;
            }
            set
            {
                _employeeModel = value;
                OnPropertyChanged("EmployeeModel");
            }
        }
 
        private ObservableCollection<EmployeeModel> _employeeModels;
        public ObservableCollection<EmployeeModel> EmployeeModels
        {
            get
            {
                return _employeeModels;
            }
            set
            {
                _employeeModels = value;
                OnPropertyChanged("EmployeeModels");
            }
        } 
 
        private void EmployeeModels_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            OnPropertyChanged("EmployeeModels");
        }
        
        public EmployeeViewModel()
        {
            EmployeeModel = new EmployeeModel();
            _employeeEntity = new Employee();
            _repository = new EmployeeRepository();
            EmployeeModels = new ObservableCollection<EmployeeModel>();
            EmployeeModels.CollectionChanged += EmployeeModels_CollectionChanged;
            GetAll();//populate grid with student information
        }
        
        public ICommand ResetCommand
        {
            get
            {
                if (_resetCommand == null)
                {
                    _resetCommand = new RelayCommand(param => this.ResetData(), null);
                }
 
                return _resetCommand;
            }
        }
 
        public ICommand SaveCommand
        {
            get
            {
                if (_saveCommand == null)
                {
                    _saveCommand = new RelayCommand(param => this.SaveData(), null);
                }
 
                return _saveCommand;
            }
        }
 
        public ICommand EditCommand
        {
            get
            {
                if (_editCommand == null)
                {
                    _editCommand = new RelayCommand(param => this.EditData((int)param), null);
                }
 
                return _editCommand;
            }
        }
        
        public ICommand DeleteCommand
        {
            get
            {
                if (_deleteCommand == null)
                {
                    _deleteCommand = new RelayCommand(param => this.DeleteEmployee((int)param), null);
                }
 
                return _deleteCommand;
            }
        }
        
    // ------------------------------------DB Operations
        private void ResetData()
        {
            EmployeeModel = new EmployeeModel();
        }
 
        private void DeleteEmployee(int id)
        {
            if (MessageBox.Show("Confirm delete of this record?", "Employee", MessageBoxButton.YesNo)
                == MessageBoxResult.Yes)
            {
               //Delete Codes here
            }
        }
 
        private void SaveData()
        {
            if (EmployeeModel != null)
            {
               //Save codes here
            }
        }
 
        private void EditData(int id)
        {
            //Edit Codes here
        }
 
        private void GetAll()
        {
            //Get All codes here
        }
    }
}
After one member gave his advice, I applied it ASAP by separating the properties and commands to it's own classes.
Employee Entity (Employee Properties)
public class EmployeeEntity : ViewModelBase
{
    public EmployeeEntity()
    {
        EmployeeModels = new ObservableCollection<EmployeeModel>();
        EmployeeModels.CollectionChanged += EmployeeModels_CollectionChanged;
    }
    
    private EmployeeModel _employeeModel;
    public EmployeeModel EmployeeModel
    {
        get
        {
            return _employeeModel;
        }
        set
        {
            _studentModel = value;
            OnPropertyChanged("EmployeeModel");
        }
    }
 
    private ObservableCollection<EmployeeModel> _employeeModels;
    public ObservableCollection<EmployeeModel> EmployeeModels
    {
        get
        {
            return _employeeModels;
        }
        set
        {
            _employeeModels = value;
            OnPropertyChanged("EmployeeModels");
        }
    }
 
    private void EmployeesModels_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        OnPropertyChanged("EmployeeModels");
    }
}
Command Class (Command Properties)
public class EmployeeCommand
{
        private ICommand _saveCommand;
        private ICommand _resetCommand;
        private ICommand _editCommand;
        private ICommand _deleteCommand;
        private EmployeeViewModel _employeeViewModel { get; set; }
 
        public EmployeeCommand(EmployeeViewModel employeeViewModel)
        {
            this._employeeViewModel = employeeViewModel;
        }
 
        public ICommand ResetCommand
        {
            get
            {
                if (_resetCommand == null)
                {
                    _resetCommand = new RelayCommand(param => _employeeViewModel.ResetData(), null);
                }

                return _resetCommand;
            }
        }
 
        public ICommand SaveCommand
        {
            //
        }
 
        public ICommand EditCommand
        {
            //
        }
 
        public ICommand DeleteCommand
        {
            //
        }
    }
View Model Class (Expose the Commands and Employee Entity)
public class EmployeeViewModel
{
    public EmployeeEntity EmployeeEntity { get; set; }
    public EmployeeCommand EmployeeCommand { get; set; }
    
     public EmployeeViewModel()
        {
            EmployeeCommand = new EmployeeCommand(this);
            EmployeeEntity = new EmployeeEntity();
            EmployeeEntity.EmployeeModel = new EmployeeModel();
            GetAll();
        }
        
        private void ResetData()
        {
            //Clear Model Codes
        }
 
        private void DeleteEmployee(int id)
        {
           //Delete Codes...
        }
 
        private void SaveData()
        {
           //Save Codes...
        }
 
        private void EditData(int id)
        {
            //Edit Codes here
        }
 
        private void GetAll()
        {
            //Get All codes here
        }
}

Now my ViewModel class looks cleaner and manageable. Cheers! :-)

0 comments:

Post a Comment