WPF and MVVM tutorial 07, the List search.

Ok, starting from this post we are going to do something really interesting. In this episode we need to create a simple List windows, but as you will see the logic will not be so different then a one-to-many form.

This will be the final result:

 

The ViewModel for the List Window.

First of all we need to create the view model. The view model should have the following commands:

  1. New – Add a new Customer
  2. Save – Save all the changes we did …
  3. Edit – Edit the current selected customer
  4. Delete – Delete the current selected customer
  5. Text box and search button – to operate search activity
  6. Exit the form

Then we need to add the following objects:

  1. An observable collection for the list of customers
  2. A current customer object, but this is not mandatory …
  3. The search information we retrieve from the view, or better, the view sends to us.

The final result will be this view model class:

 

Let’s have a look at the View Model commands. As you know when we assign a RelayCommand, we can do it in 2 ways:

By passing with a lambda expression the corresponding action.

By passing with a lambda expression the corresponding action and a predicate (something like true/false).

So for some commands like Save or Delete we can also build a predicate action like CanSave? CanDelete? and encapsulating some validation logic inside.

So the code should look like:

 

The RelayCommands.

Simple command like Create a new customer:

  1: //Private field
  2: public ViewCommand newCommand;
  3: //Public property to be assigned in the XAML code
  4: public ViewCommand NewCommand {
  5:    get {
  6:       if (newCommand == null)
  7:          newCommand = 
  8:          //Lambda expression for assigning the action
  9:          new ViewCommand(param => this.NewCustomer());
 10:       return newCommand;
 11:    }
 12: }
 13: //Real routine executed in the ViewModel
 14: private void NewCustomer() {
 15:    NavigationActions.OpenCustomerView();
 16: }
 17:

Or something more complex like Delete a customer:

  1: //Private command field
  2: private ViewCommand deleteCommand;
  3: //Public databinded ICommand
  4: public ViewCommand DeleteCommand {
  5:    get {
  6:       if (deleteCommand == null) {
  7:       deleteCommand = new ViewCommand(
  8:           param=>this.DeleteCustomer(),
  9:           //Lambda expression for evaluating the execution
 10:           param=>this.CanDeleteCustomer
 11:           );
 12:       }   
 13:       return deleteCommand;
 14:    }
 15: }
 16: //Real delete command
 17: public void DeleteCustomer() {
 18:    if (SelectedCustomer != null) {
 19:       if(NavigationActions.QueryConfirmation(
 20:          "Delete Customer.",
 21:          string.Format("Do you want to delete {0}?",SelectedCustomer.FirstName))){
 22:          ListOfCustomers.Remove(SelectedCustomer);
 23:          repository.DeleteCustomer(SelectedCustomer);
 24:       }
 25:    } else {
 26:       NavigationActions.ShowError(
 27:         "Delete Customer.", 
 28:         "You must select a Customer!");
 29:    }
 30: }
 31: //Additional logic can go here ...
 32: private bool CanDeleteCustomer {
 33:    get { return true; }
 34: }
 35:

Then of course we will have two different command for Edit a Customer or create a new one, and at the end the difference will be just here:

  1: //Open the Customer window empty
  2: NavigationActions.OpenCustomerView();

  4: NavigationActions.OpenCustomerView(SelectedCustomer);
  3: //Open the Customer window passing a Customer
  5:
  6:

The others commands are the same, but if you want in my solution you can find the complete implementation.

Loading and working with a Collection.

After we build all the commands and we bind them to the XAML code, we need to load our entities. For this we will use a ObservableCollection List that we will implement in the initialization of our View Model, so when the Window will open we will also load the Collection inside the ListView.

  1: //We need an instance of our repository
  2: CustomerRepository repository;
  3: //This will contain our Customers
  4: ObservableCollection<Customer> listOfCustomers;
  5: //This will be the current selected customer
  6: Customer selectedCustomer;
  7: public CustomersViewModel() {
  8:    if (repository == null) {
  9:       //Initialization of the Repository
 10:       repository = new CustomerRepository();
 11:    }
 12:    Initialization of the List
 13:    listOfCustomers = 
 14:       new ObservableCollection<Customer>(
 15:          repository.GetAllCustomers());
 16:    this.SearchText = "Some text to search ...";
 17: }
 18: //Binded property containing the Customer list
 19: public ObservableCollection<Customer> ListOfCustomers {
 20:    get { return listOfCustomers; }
 21: }
 22:

INotifyPropertyChanged

If we want to advise the UI that we loaded a new customers list, we have to build a ViewModel that implements the INotifyPropertyChanged in this way:

  1: #region INotifyPropertyChanged Members
  2: 
  3: public event PropertyChangedEventHandler PropertyChanged;
  4: 
  5: public void NotifyPropertyChanged(String info) {
  6:    if (PropertyChanged != null) {
  7:       PropertyChanged(
  8:          this, 
  9:          new PropertyChangedEventArgs(info)
 10:       );
 11:    }
 12: }
 13: 
 14: #endregion

And then change the property code in this way:

  1: public ObservableCollection<Customer> ListOfCustomers {
  2:     
  3:     get { return listOfCustomers; }
  4:     private set {
  5:         if (listOfCustomers != value) {
  6:             listOfCustomers = value;
  7:             NotifyPropertyChanged("ListOfCustomers");
  8:         }
  9:     }
 10: }

Now, everytime we are going to load something new into the collection, or we are going to use a view of the collection the ViewModel will send a message in the view saying “Hey, look I changed something in the list, update the UI!!”.

Leave a comment

Your email address will not be published. Required fields are marked *