Data Access has been discontinued. Please refer to this page for more information.

Saving New or Edited Cars

In this step you will add the functionality to save a new or edited car to the database and expose commands for the view to bind to. You will need to implement the required methods and expose command objects based on them.

Implementing the required methods

  1. In the constructor add a call to a method which will be defined shortly - InitializeCurrentCarAndTitle.

    this.InitializeCurrentCarAndTitle();
    
    Me.InitializeCurrentCarAndTitle()
    
  2. Create a new method called InitializeCurrentCarAndTitle. This model will initialize currentCar and title depending on wheter a car Id has been passed to the view model`s constructor. If a car Id has been passed, the view model is in edit mode, if there is no car Id, the view model is in add mode.

    private void InitializeCurrentCarAndTitle()
    {
        if (this.currentCarId.HasValue)
        {
            //The view model is in Edit mode
            this.CurrentCar = this.context.Cars.FirstOrDefault(car => car.CarID == this.currentCarId.Value);
            this.Title = EDIT_MODE_TITLE;
        }
        else
        {
            //The view model is in Add mode
            this.CurrentCar = new Car()
            {
                Latitude = 0.000000d,
                Longitude = 0.000000d
            };
            this.Title = ADD_MODE_TITLE;
        }
        if (this.CurrentCar.CarYear.HasValue == false)
        {
            this.CurrentCar.CarYear = (short)DateTime.Now.Year;
        }
    }
    
    Private Sub InitializeCurrentCarAndTitle()
        If Me._currentCarId.HasValue Then
            'The view model is in Edit mode
            Me.CurrentCar = Me._context.Cars.FirstOrDefault(Function(car) car.CarID = Me._currentCarId)
            Me.Title = EDIT_MODE_TITLE
        Else
            'The view model is in Add mode
            Me.CurrentCar = New Car() With {.Latitude = 0D, .Longitude = 0D}
            Me.Title = ADD_MODE_TITLE
        End If
        If Me.CurrentCar.CarYear.HasValue = False Then
            Me.CurrentCar.CarYear = DateTime.Now.Year
        End If
    End Sub
    
  3. Add a new method called Save. This method will add the CurrentCar object in the database if the view model is in add mode or save the changes made to CurrentCar if the view model is in edit mode.

    private void Save()
    {
        if (this.currentCarId.HasValue == false)
        {
            //Add the new car to the context
            this.context.Add(this.CurrentCar);
        }
        try
        {
            if (this.context.HasChanges)
            {
                this.context.SaveChanges();
            }
            this.OperationIsSuccessful = true;
        }
        catch (DataStoreException ex)
        {
            this.HandleException(ex.BackendError.Description);
            return;
        }
        catch (DuplicateKeyException ex)
        {
            this.HandleException(ex.BackendError.Description);
            return;
        }
        catch (Exception ex)
        {
            this.HandleException(ex.Message);
            return;
        }
    }
    
    Private Sub Save()
        If Me._currentCarId.HasValue = False Then
            'Add the new car to the context
            Me._context.Add(Me.CurrentCar)
        End If
        Try
            If Me._context.HasChanges Then
                Me._context.SaveChanges()
            End If
            Me.OperationIsSuccessful = True
        Catch ex As DataStoreException
            Me.HandleException(ex.BackendError.Description)
            Exit Sub
        Catch ex As DuplicateKeyException
            Me.HandleException(ex.BackendError.Description)
            Exit Sub
        Catch ex As Exception
            Me.HandleException(ex.Message)
            Exit Sub
        End Try
    End Sub
    
  4. Create the HandleException method. It is called from Save() and takes as an argument the exception message which should be displayed. Displays a message box with information about the occurred error, and causes the view`s controls displaying information about the car to rebind.

    private void HandleException(string exceptionMessage)
    {
        MessageBox.Show(SAVE_ERROR_MESSAGE + exceptionMessage, SAVE_ERROR_TITLE, MessageBoxButton.OK, MessageBoxImage.Error);
        this.OperationIsSuccessful = null;
        //Cause binding refresh
        this.RaisePropertyChanged("CurrentCar");
    }
    
    Private Sub HandleException(exceptionMessage As String)
        MessageBox.Show(SAVE_ERROR_MESSAGE + exceptionMessage, SAVE_ERROR_TITLE, MessageBoxButton.OK, MessageBoxImage.Error)
        Me.OperationIsSuccessful = Nothing
        'Cause binding refresh
        Me.RaisePropertyChanged("CurrentCar")
    End Sub
    
  5. Create a method called Cancel. Here you should call the Close method of the related view.

    private void Cancel()
    {
        this.View.Close();
    }
    
    Private Sub Cancel()
        Me.View.Close()
    End Sub
    

Exposing commands to the the view

Now you need to expose commands based on the methods Save and Cancel to the view.

  1. Create a property called SaveCommand. In its getter, initialize a RelayCommand object based on the Save method and return it.

    public RelayCommand SaveCommand
    {
        get
        {
            this.command = new RelayCommand(this.Save);
            return this.command;
        }
        set
        {
            this.command = value;
        }
    }
    
    Public Property SaveCommand As RelayCommand
        Get
            Me._command = New RelayCommand(AddressOf Me.Save)
            Return Me._command
        End Get
        Set(value As RelayCommand)
            Me._command = value
        End Set
    End Property
    
  2. Create a property called CancelCommand. In its getter, initialize a RelayCommand object based on the Cancel method and return it.

    public RelayCommand CancelCommand
    {
        get
        {
            this.command = new RelayCommand(this.Cancel);
            return this.command;
        }
        set
        {
            this.command = value;
        }
    }
    
    Public Property CancelCommand As RelayCommand
        Get
            Me._command = New RelayCommand(AddressOf Me.Cancel)
            Return Me._command
        End Get
        Set(value As RelayCommand)
            Me._command = value
        End Set
    End Property
    

Disposing the context

  1. In AddEditViewModel implement the IDisposable interface to make it disposable. In the Dispose method, dispose the OpenAccessContext object. This way when the view model is no longer needed and thus disposed, the context will be disposed as with it.

    public void Dispose()
    {
        //The context is local to the ViewModel and must be disposed together with it
        if (this.context != null)
        {
            this.context.Dispose();
        }
    }
    
    Public Sub Dispose() Implements IDisposable.Dispose
        'The context is local to the ViewModel and must be disposed together with it
        If IsNothing(Me._context) = False Then
            _context.Dispose()
        End If
    End Sub
    

Next step: Initializing AddEditModel