#7 Creating a MVVM WPF Rest App

Creating a MVVM WPF Rest App

In this blog were going to carry on with out Lambda project, and build a desktop app that will use the API end points. We’ll create the application using WPF (Windows Presentation Foundation), with M-V-VM (Model-View-ViewModel). If you don’t know what MVVM is its essentially abstracting away the code normally found within the UI to it’s own layer with some cleverness. It comes in three parts; The Model which is the properties that define the data object and any Model specific methods, in our case it will be the DataModel Class we previously created, but were going to add some additional stuff. The View which is essentially our UI (User Interface) so nothing to special there, except that all the behind code is abstracted away. Finally the ViewModel which is the class that contains the abstracted UI code. So lets get started…

Visual Studio Project

So were going to create a new Visual Studio project, that is a WPF DotNet Core 3.1 project. Within the project well add three project folders for; Infrastructure, Models, and ViewModels. The rest well talk about in steps.

Visual Studio Project Structure

RestData

Were going to stub out this class and come back to it later on, but we need the public methods to allow us to write ViewModel. When we created the Lambda Rest API end points we end up with a URL and API key both of these you will need to and replace in the code below.

using DataModel_UI.Models;
using Newtonsoft.Json;

using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

namespace DataModel_UI.Infrastructure
{
    public static class RestData
    {
        private static HttpClient Client = new HttpClient();

        private static string _Url = @"https://XXXXXXXXXXXXXXX.execute-api.eu-west-1.amazonaws.com/Prod/v1/DataModel";
        private static string _APIKey = @"YYYYYYYYYYYYYYYYY";

        #region Create DataModel Data
        public static DataModel CreateDataModel(DataModel NewDataModel)
        {
            Task<DataModel> ApplicationTask = RestData.CreateDataModels(NewDataModel);
            ApplicationTask.Wait();
            return ApplicationTask.Result;
        }
        private static async Task<DataModel> CreateDataModels(DataModel NewDataModel)
        {
            DataModel ReturnDataModel = null;
            return ReturnDataModel;
        }
        #endregion

        #region Delete DataModel Data
        public static bool DeleteDataModel(DataModel DeleteDataModel)
        {
            Task<bool> ApplicationTask = RestData.DeleteDataModels(DeleteDataModel);
            ApplicationTask.Wait();
            return ApplicationTask.Result;
        }
        private static async Task<bool> DeleteDataModels(DataModel DeleteDataModel)
        {
            bool ReturnBoolean = false;
            return ReturnBoolean;
        }
        #endregion

        #region Get DataModels
        public static ObservableCollection<DataModel> GetDataModel()
        {
            ObservableCollection<DataModel> ReturnApplicationModels = null;
            return ReturnApplicationModels;
        }
        private static async Task<ObservableCollection<DataModel>> GetDataModels()
        {
            ObservableCollection<DataModel> ReturnContinents = null;
            return ReturnContinents;
        }
        #endregion

        #region Update DataModel Data
        public static DataModel UpdateDataModel(DataModel OriginalContinent, DataModel ToBe)
        {
            DataModel ReturnDataModel = null;
            return ReturnDataModel;
        }
        private static async Task<DataModel> UpdateDataModels(ChangeDataModelRequest changeContinentRequest)
        {
            DataModel ReturnDataModel = null;
            return ReturnDataModel;
        }
        #endregion
          
        private static T DeserializeObject<T>(string iJSonString)
        {
            return JsonConvert.DeserializeObject<T>(iJSonString);
        }
    }
}

Model

There are a couple of things we need to create before we get to the two models. Were going to create a class to implement the INotifyPropertyChanged interface as a base models class. So let’s get to it.

BaseModel

The very first thing were going to do is create a class that Implements INotifyPropertyChanged, which means we have to implement the Event ‘PropertyChangedEventHandler’ and the Method ‘NotifyPropertyChanged’, this is done as shown below. This allows us to automatically raise an event when a property is changed and reflect that within the user interface. Since we have done this in the BaseModel class all of our models will inherit this piece of code.

using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace DataModel_UI.Models
{
    public abstract class BaseModel : INotifyPropertyChanged
    {
        #region INotifyPropertyChanged Members
        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion
    }
}

DataModel – Model

There is a lot going on in here, notice we inherit from the BaseModel otherwise the change events would not be raised. Also our DataModel needs three propertys; FirstName, LastName, and Age. Each property has a private data member and a public Getter and Setter, within the setter we also call the ‘NotifyPropertyChanged’ call, to raise the event.

I also added a default constructor and a constructor that takes three arguments for; FirstName, LastName, and Age.

Then some methods that directly belong to the model for; Update, and Wipe, these will be used later on.

Lastly, I overrode the Equals method, strictly speaking I should have also overrode the GetHashCode method as well, but you can get away with it.

namespace DataModel_UI.Models
{
    public class DataModel : BaseModel
    {
        string _FirstName;
        public string FirstName
        {
            get => _FirstName;
            set { _FirstName = value; NotifyPropertyChanged(); }
        }

        string _LastName;
        public string LastName
        {
            get => _LastName;
            set { _LastName = value; NotifyPropertyChanged(); }
        }

        int _Age;
        public int Age
        {
            get => _Age;
            set { _Age = value; NotifyPropertyChanged(); }
        }

        public DataModel() { }
        public DataModel(string iFirstName, string iLastName, int iAge)
        {
            FirstName = iFirstName;
            LastName = iLastName;
            Age = iAge;
        }

        public void Update(string iFirstName, string iLastName, int iAge)
        {
            FirstName = iFirstName;
            LastName = iLastName;
            Age = iAge;
        }

        public void Update(DataModel iDataModel)
        {
            FirstName = iDataModel.FirstName;
            LastName = iDataModel.LastName;
            Age = iDataModel.Age;
        }

        public void Wipe()
        {
            FirstName = string.Empty;
            LastName = string.Empty;
            Age = 0;
        }

        public override bool Equals(object obj)
        {
            bool ReturnBoolean = false;
            if(obj is DataModel)
            {
                DataModel DM = (DataModel)obj;
                if(DM.FirstName == FirstName && DM.LastName == LastName && DM.Age == Age)
                {
                    ReturnBoolean = true;
                }
            }
            return ReturnBoolean;
        }
    }
}

ChangeDataModelRequest – Model

In similar fashion I updated the ‘ChangeDatamodelRequest’ model to use call the ‘NotifyPropertyChanged’ call, to raise the change event. Now our models are completed we can move on to the next bit.

namespace DataModel_UI.Models
{
    public class ChangeDataModelRequest : BaseModel
    {
        DataModel _Original;
        public DataModel Original
        {
            get => _Original;
            set { _Original = value; NotifyPropertyChanged(); }
        }

        DataModel _ToBe;
        public DataModel ToBe
        {
            get => _ToBe;
            set { _ToBe = value; NotifyPropertyChanged(); }
        }

        public ChangeDataModelRequest() { }
        public ChangeDataModelRequest(DataModel iOriginal, DataModel iToBe) 
        {
            Original = iOriginal;
            ToBe = iToBe;
        }
    }
}

RelayCommand

In engineering we have a saying ‘Copy with Pride’, so I will be completely honest I found this on the web and it works so I’m not asking to many questions. Essentially this class implements ICommand and allows us to relay actions from the UI (user Interface) to the ViewModel, where those actions are handled.

using System;
using System.Windows.Input;

namespace DataModel_UI.Infrastructure
{
    public class RelayCommand : ICommand
    {
        readonly Action<object> _execute;
        readonly Predicate<object> _canExecute;

        public RelayCommand(Action<object> execute, Predicate<object> canExecute)
        {
            if (execute == null)
            {
                throw new NullReferenceException("execute");
            }
            else
            {
                this._execute = execute;
                this._canExecute = canExecute;
            }
        }
        public RelayCommand(Action<object> execute) : this(execute, null)
        {

        }

        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }
        public bool CanExecute(object parameter)
        {
            return this._canExecute == null ? true : this._canExecute(parameter);
        }
        public void Execute(object parameter)
        {
            this._execute.Invoke(parameter);
        }
    }
}

DataViewModel – ViewModel

Were going to break down the ViewModel, into steps, first were going to use our RelayCommand to create four actions; Add New Data Model, Clear Data Model, Delete Data Model, and Update Data Model. These will be associated to the four buttons in the View; Add, Clear, Delete, and Update. Each one has two methods defined one for the Click action and one to determine if the button is Active or not, this is really cool as we can add state logic. These Relay Command property’s and initiated in the constructor.

using DataModel_UI.Infrastructure;
using DataModel_UI.Models;

using System;
using System.Collections.ObjectModel;
using System.Linq;

namespace DataModel_UI.ViewModels
{
    public class DataViewModel
    {
        public RelayCommand Btn_AddNewDataModel_Click { get; private set; }
        public RelayCommand Btn_ClearDataModel_Click { get; private set; }
        public RelayCommand Btn_DeleteDataModel_Click { get; private set; }
        public RelayCommand Btn_UpdateDataModel_Click { get; private set; }
      
        public DataViewModel()
        {
            Btn_AddNewDataModel_Click = new RelayCommand(AddNewDataModel, CanAddNewDataModel);
            Btn_ClearDataModel_Click = new RelayCommand(ClearDataModel, CanClearDataModel);
            Btn_DeleteDataModel_Click = new RelayCommand(DeleteDataModel, CanDeleteDataModel);
            Btn_UpdateDataModel_Click = new RelayCommand(UpdateDataModel, CanUpdateDataModel);
        }
      
        public void AddNewDataModel(object message){}
        public bool CanAddNewDataModel(object message){}
      
        public void ClearDataModel(object message){}
        public bool CanClearDataModel(object message){} 

        public void DeleteDataModel(object message){}
        public bool CanDeleteDataModel(object message){}
      
        public void UpdateDataModel(object message){}
        public bool CanUpdateDataModel(object message){}
	}
}

Next were going to add some simple public and private data members, for the main Collection of DataModels we can not just use a ‘List’ or ‘IEnumerable’, we must use an ObservableCollection, this is a collection that allows code outside the collection be aware of when changes to the collection (add, move, remove) occur. It is used heavily in WPF and Silverlight but its use is not limited to there. Code can add event handlers to see when the collection has changed and then react through the event handler to do some additional processing. This may be changing a UI or performing some other operation.

We’re also going to initialize these within the constructor, except for _Original, well deal with that as we go.

        DataModel _Original;

        DataModel _CurrentDataModel;
        public DataModel CurrentDataModel
        {
            get => _CurrentDataModel;
            set { _CurrentDataModel = value; }
        }

        private ObservableCollection<DataModel> _DataModelsCollection;
        public ObservableCollection<DataModel> DataModelsCollection
        {
            get => _DataModelsCollection;
            set
            {
                if (value == _DataModelsCollection)
                    return;
                _DataModelsCollection = value;
            }
        }

        public DataViewModel()
        {
            CurrentDataModel = new DataModel();
            DataModelsCollection = RestData.GetDataModel();
            if (DataModelsCollection == null) { DataModelsCollection = new ObservableCollection<DataModel>(); }

            Btn_AddNewDataModel_Click = new RelayCommand(AddNewDataModel, CanAddNewDataModel);
            Btn_ClearDataModel_Click = new RelayCommand(ClearDataModel, CanClearDataModel);
            Btn_DeleteDataModel_Click = new RelayCommand(DeleteDataModel, CanDeleteDataModel);
            Btn_UpdateDataModel_Click = new RelayCommand(UpdateDataModel, CanUpdateDataModel);
        }

Add New Data Model

The ‘AddNewDataModel’ is not to interesting other than the call to the RestData,CreateDataModel. If the DataModel is added successfully, then the DataModel is added to the Data Models Collection. Then we do reset the ‘CurrentDataModel’ by wiping the attributes (not nulling the object) and nulling the ‘_Original’ DataModel this will become clear as we go.

        public void AddNewDataModel(object message)
        {
            try
            {
                DataModel DataModel=RestData.CreateDataModel(CurrentDataModel);
                if (DataModel != null)
                {                 
                    DataModelsCollection.Add(DataModel);
                    CurrentDataModel.Wipe();
                    _Original = null;
                }
            }
            catch(Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

However, the ‘CanAddNewDataModel’ is really interesting, were always going to return False to assume that the button is deactivated, unless…

First thing is well check to see if the message is a ‘DataModel’ if it is we will convert the message object to a DataModel and check if it’s null. Next we will check to see if any of the DataModel attributes are ‘NotNull or White Space, and that the Age value is not 0 (although that should be greater than 0).

To protect, for the case in which the Data Models Collection is null we will return true, otherwise we will do one more validation to see if the Data models Collection already contains the new DataModel’s definition, if not Activate the button to allow the user to add the new DataModel.

        public bool CanAddNewDataModel(object message)
        {
            bool ReturnBoolean = false;
            if (message is DataModel)
            {
                DataModel DataModel = (DataModel)message;
                if (DataModel != null)
                {
                    if (!string.IsNullOrWhiteSpace(DataModel.FirstName) &&
                        !string.IsNullOrWhiteSpace(DataModel.LastName) &&
                        !string.IsNullOrWhiteSpace(Convert.ToString(DataModel.Age)) &&
                        DataModel.Age != 0)
                    {
                        if (DataModelsCollection == null)
                        {
                            ReturnBoolean = true;
                        }
                        else
                        {
                            if(!DataModelsCollection.Any(CDM => CDM.Equals(DataModel) == true))
                            {
                                ReturnBoolean = true;
                            }
                        }
                    }
                }
            }
            return ReturnBoolean;
        }

Clear Data Model

The ‘ClearNewDataModel’ is even less interesting it does not even call a Rest API. What it does do is clears the text fields by wiping the ‘CurrentDataModel’ attributes (not nulling the object) and nulling the ‘_Original’ DataModel.

        public void ClearDataModel(object message)
        {
            try
            {
                CurrentDataModel.Wipe();
                _Original = null;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

The ‘CanClearDataModel’ will again always return False to assume that the button is deactivated, unless…

First thing is well check to see if the message is a ‘DataModel’ if it is we will convert the message object to a DataModel and check if it’s null. Next we will check to see if any of the DataModel attributes are ‘NotNull or White Space, and that the Age value is not 0 (although that should be greater than 0).

If these requirements are met, then the return Boolean value will be true activating the button and allowing the user to clear the text fields.

        public bool CanClearDataModel(object message)
        {
            bool ReturnBoolean = false;
            if (message is DataModel)
            {
                DataModel DataModel = (DataModel)message;
                if (DataModel != null)
                {
                    if (!string.IsNullOrWhiteSpace(DataModel.FirstName) ||
                        !string.IsNullOrWhiteSpace(DataModel.LastName) ||
                        !string.IsNullOrWhiteSpace(Convert.ToString(DataModel.Age)) &&
                        DataModel.Age != 0)
                    {
                        ReturnBoolean = true;
                    }
                }
            }
            return ReturnBoolean;
        }

Delete Data Model

The ‘DeleteDataModel’ is not to interesting other than the call to the RestData,DeleteDataModel. If the DataModel is deleted successfully the first thing is to remove the DataModel form the Data models Collection, then we reset the ‘CurrentDataModel’ by wiping the attributes and nulling the ‘_Original’ DataModel.

        public void DeleteDataModel(object message)
        {
            try
            {
                if (message is DataModel)
                {
                    DataModel DataModel = (DataModel)message;

                    bool WasDeleted = RestData.DeleteDataModel(DataModel);
                    if (WasDeleted == true)
                    {
                        DataModelsCollection.Remove(DataModel);
                        CurrentDataModel.Wipe();
                        _Original = null;
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

The ‘CanDeleteDataModel’ will again always return False to assume that the button is deactivated, unless…

First thing is well check to see if the message is a ‘DataModel’ if it is we will convert the message object to a DataModel and check if it’s null. Next we will check to see if any of the DataModel attributes are ‘NotNull or White Space, and that the Age value is not 0.

To protect, for the case in which the Data Models Collection is null we will return true, otherwise we will do one more validation to see if the Data models Collection already contains DataModel’s definition, if it does Activate the button to allow the user to Delete the DataModel.

        public bool CanDeleteDataModel(object message)
        {
            bool ReturnBoolean = false;
            if (message is DataModel)
            {
                DataModel DataModel = (DataModel)message;
                if (DataModel != null)
                {
                    if (!string.IsNullOrWhiteSpace(DataModel.FirstName) &&
                        !string.IsNullOrWhiteSpace(DataModel.LastName) &&
                        !string.IsNullOrWhiteSpace(Convert.ToString(DataModel.Age)) &&
                        DataModel.Age != 0)
                    {
                        if (DataModelsCollection == null)
                        {
                            ReturnBoolean = true;
                        }
                        else
                        {
                            if (DataModelsCollection.Any(CDM => CDM.Equals(DataModel) == true))
                            {
                                ReturnBoolean = true;
                            }
                        }
                    }
                }
            }
            return ReturnBoolean;
        }

Update Data Model

The ‘UpdateDataModel’ makes the call to the RestData,UpdateDataModel by using the ‘_Original’ and ‘CurrentDataModel’ DataModel’s. If the DataModel is updated successfully the first thing is to update the DataModel in the Data models Collection, then we reset the ‘CurrentDataModel’ by wiping the attributes and nulling the ‘_Original’ DataModel.

        public void UpdateDataModel(object message)
        {
            try
            {
                DataModel DataModel = RestData.UpdateDataModel(_Original,CurrentDataModel);
                if (DataModel != null)
                {
                    DataModel OriginalDataModel = DataModelsCollection.ElementAt(DataModelsCollection.IndexOf(_Original));
                    OriginalDataModel.Update(CurrentDataModel);
                    CurrentDataModel.Wipe();
                    _Original = null;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

The ‘CanUpdateDataModel’ is much simpler than the other methods we still assume that the button will be deactivated, the main validation is to validate that the updated DataModel is not identical to any other DataModel within the Data models Collection. If the DataModel is different then activate the button and allow the user to update the DataModel.

        public bool CanUpdateDataModel(object message)
        {
            bool ReturnBoolean = false;
            if (message is DataModel && _Original!=null)
            {
                DataModel DataModel = (DataModel)message;
                if(!DataModel.Equals(_Original))
                {
                    ReturnBoolean = true;
                }
            }
            return ReturnBoolean;
        }

Data Grid View Selected Item

The last thing we need to do is to capture the Data Grid View Item Change Event to do this we will create a property that when set calls a private method that updates the Current DataModel and sets the Original DataModel, we will bind to this in the XAML to make it all work.

        DataModel _Dgv_SelectedItem;
        public DataModel Dgv_SelectedItem
        {
            get => this._Dgv_SelectedItem;
            set { this._Dgv_SelectedItem = value; this.Dgv_DataModel_ItemChanged(value); }
        }
        public void Dgv_DataModel_ItemChanged(DataModel iDataModel)
        {
            if (iDataModel != null)
            {
                CurrentDataModel.Update(iDataModel.FirstName, iDataModel.LastName, iDataModel.Age);
                _Original = iDataModel;
            }
        }

WPF XAML – View

There is lots going on in here especially with the binding, but here I want to concentrate on the MVVM structure.

<Window x:Class="DataModel_UserInterface.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:DataModel_UserInterface"
        mc:Ignorable="d"
        Title="Data Model App" Height="450" Width="800">
    <Grid>

        <DataGrid Name ="Dtg_DataModels"
                  AutoGenerateColumns="False"
                  ItemsSource="{Binding   DataModelsCollection, 
                                          Mode=TwoWay, 
                                          NotifyOnSourceUpdated=True, 
                                          UpdateSourceTrigger=PropertyChanged}"
                      
                  SelectedItem="{Binding  Dgv_SelectedItem,
                                          Mode=TwoWay,
                                          NotifyOnSourceUpdated=True,
                                          UpdateSourceTrigger=PropertyChanged}"
                                    
                  ColumnWidth="*" 
                  Background="#FF9F9E9E"
                  Margin="363,10,9.6,10">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding FirstName,
                                                      Mode=TwoWay, 
                                                      NotifyOnSourceUpdated=True, 
                                                      UpdateSourceTrigger=PropertyChanged}" 
                                    Header="First Name" IsReadOnly="True"/>
                <DataGridTextColumn Binding="{Binding LastName,
                                                      Mode=TwoWay, 
                                                      NotifyOnSourceUpdated=True, 
                                                      UpdateSourceTrigger=PropertyChanged}" 
                                    Header="Last Name" IsReadOnly="True"/>
                <DataGridTextColumn Binding="{Binding Age,
                                                      Mode=TwoWay, 
                                                      NotifyOnSourceUpdated=True, 
                                                      UpdateSourceTrigger=PropertyChanged}" 
                                    Header="Age" IsReadOnly="True"/>
            </DataGrid.Columns>
        </DataGrid>

        <Button Name="Btn_Add" 
                Content="Add"
                Height="23"
                Width="75"
                Margin="10,275,0,0"
                HorizontalAlignment="Left"             
                VerticalAlignment="Top"               
                Command="{Binding Btn_AddNewDataModel_Click}" 
                CommandParameter="{Binding  Path=CurrentDataModel}"/>

        <Button Name ="Btn_Clear" 
                Content="Clear"
                Height="23"
                Width="75"
                Margin="138,222,0,0" 
                HorizontalAlignment="Left" 
                VerticalAlignment="Top"
                Command="{Binding Btn_ClearDataModel_Click}" 
                CommandParameter="{Binding Path=CurrentDataModel}"/>
        
        <Button Name="Btn_Remove" 
                Content="Remove"
                Height="23"
                Width="75"
                Margin="138,275,0,0"
                HorizontalAlignment="Left"             
                VerticalAlignment="Top"               
                Command="{Binding Btn_DeleteDataModel_Click}" 
                CommandParameter="{Binding  Path=CurrentDataModel}"/>

        <Button Name ="Btn_Update" 
                Content="Update"
                Height="23"
                Width="75"
                Margin="10,222,0,0" 
                HorizontalAlignment="Left" 
                VerticalAlignment="Top"
                Command="{Binding Btn_UpdateDataModel_Click}" 
                CommandParameter="{Binding  Path=CurrentDataModel}"/>

        
        <Label Content="First Name" HorizontalAlignment="Left" Margin="10,10,0,0" Height="26" VerticalAlignment="Top"/>
        <TextBox Name="Txt_FirstName"                 
                 Height="23"
                 Width="203" 
                 Margin="10,41,0,0"
                 HorizontalAlignment="Left"
                 VerticalAlignment="Top"
                 Text="{Binding  Path=CurrentDataModel.FirstName,
                                 Mode=TwoWay,
                                 NotifyOnSourceUpdated=True,
                                 UpdateSourceTrigger=PropertyChanged}"  />

        <Label Content="Last Name" HorizontalAlignment="Left" Margin="10,69,0,0" VerticalAlignment="Top"/>
        <TextBox Name="Txt_LastName"                
                 Height="23"
                 Width="203"
                 Margin="10,100,0,0"                 
                 HorizontalAlignment="Left"
                 VerticalAlignment="Top"
                 Text="{Binding Path=CurrentDataModel.LastName,
                                 Mode=TwoWay,
                                 NotifyOnSourceUpdated=True,
                                 UpdateSourceTrigger=PropertyChanged}"  />

        <Label Content="Age" HorizontalAlignment="Left" Margin="10,128,0,0" VerticalAlignment="Top"/>
        <TextBox Name="Txt_Age" 
                 Height="23"  
                 Width="203" 
                 Margin="10,158,0,0" 
                 HorizontalAlignment="Left" 
                 VerticalAlignment="Top"
                 Text="{Binding  Path=CurrentDataModel.Age,
                                 Mode=TwoWay,
                                 NotifyOnSourceUpdated=True,
                                 UpdateSourceTrigger=PropertyChanged}"  />
    </Grid>
</Window>

Within the ‘XAML.cs’ file we need to set the DataContext to a new instance of the ViewModel, this will allow the the bindings to work, including the relays.

using DataModel_UI.ViewModels;
using System.Windows;

namespace DataModel_UserInterface
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new DataViewModel();
        }
    }
}

Testing Our App

Making our App Look Nicer