This is the second article in a series about implementing Model-View-ViewModel in client side Blazor. In the first article located here we took the default hosted Blazor app template and re-implemented the FetchData page using MVVM with a separate View, ViewModel and Model:

In this article we are going to add some additional functionality to the sample client we built. The goal is to show a few scenarios similar to what may be encountered when building a standard line of business application. The code for the project is located at this repository in GitHub:

The starting point for this article is the end of the previous article and that code is available in the ArticleOne branch or from the 4.1 release. The end point of this article will be the ArticleTwo branch and the 4.2 release.

Customizing the view of your data with the ViewModel

In the first article the `RetrieveForecastsAsync()` method in FetchDataModel called the Web API and directly returned the WeatherForecast[] to the ViewModel. This is not a proper model implementation but was done for simplicity when putting the example application together. Our Model should hold our objects and associated logic and the ViewModel should only hold what is needed for presenting that data in the View. We are going to update our Model to hold our WeatherForecast[] and then implement a “new requirement from the business” in our application.

In our fictitious scenario our business has found a new cloud based provider that will give us forecast data for half the cost of the current provider. The only catch is that they only provide the data in Celsius and not in Fahrenheit. The marketing department is aware that we can calculate the number ourselves using the provided data but they have also decided that giving both numbers to the users at the same time is overwhelming and confuses them when they use the application. It has been decided that the application must now only display one temperature scale and provide a toggle option to change back and forth. The default is to display Fahrenheit when the application loads because the focus study group found Celsius too confusing.

To simulate the change in service provider we’re going to implement an IWeatherForecast interface and not include the TemperatureF property in it. Our WeatherForecast class now looks like this:

Updating the Model

We want to properly store the retrieved data in the Model. To do this we’re going to add a private member variable as well as a public method to allow the ViewModel to access our Forecasts. On the method we are making the setter private as the ViewModel is not allowed to alter data in the Model. This is the code we have added:

private IWeatherForecast[] _weatherForecasts;

public IWeatherForecast[] WeatherForecasts { get => _weatherForecasts; private set => _weatherForecasts = value; }

We do not want to return our WeatherForecast[] array any longer; the ViewModel is going to access the public property on the Model now. We have to store the results of our Web API call in the Model so we are changing the signature and the code on RetrieveForecastsAsync() so it now reads as follows:

public async Task RetrieveForecastsAsync()

{

_weatherForecasts = await _http.GetJsonAsync<WeatherForecast[]>

("api/SampleData/WeatherForecasts");

}

This also requires changing our IFetchDataModel so it matches the new code by updating the existing method and adding the needed public property for WeatherForecasts. Our Model now looks like this:

Updating the ViewModel

We now have to open our ViewModel and rewrite the `RetrieveForecastsAsync()` method. First we remove the assignment to the local private variable that we are no longer using then we add code to populate our variable from the public property in the Model. In a lot of real world scenarios we would be using a completely different class to hold the data we are presenting to the view but in this simple example we are going to stick with the WeatherForecast class. Then we go through and change all the references of WeatherForecast to become references of IWeatherForeCast. The new code for FetchDataViewModel- is as follows:

The final step to getting our updated project to build is now to go into FetchDataView and deleting the <th> line for Temp. (F) and deleting the <td> line for @forecast.TemperatureF. We have our “new service provider” implemented but after coming all this way we now have what looks like the same app we already had but with less information displayed.

Adding the new features

Now that our application is working again let’s put the new requirements that we’ve been given in place. Let’s start with defaulting to displaying the temperature in Fahrenheit. Since we already know that we’re going to be swapping back and forth we can add a new private boolean variable into our ViewModel.

private bool _displayFahrenheit;

We will set the value to true in our constructor

_displayFahrenheit = true;

then add the following public property and method to our ViewModel. We can then use our Ctrl + . Quick Actions to pull them up to IFetchDataViewModel.

public string DisplayTemperatureScaleShort

{

get

{

return _displayFahrenheit ? "F" : "C";

}

} public int DisplayTemperature(int temperature)

{

return _displayFahrenheit ? 32 + (int)(temperature / 0.5556) :

temperature;

}

We will now use the publicly available property to update the table header in our View

<th>Temp. (@fetchDataViewModel.DisplayTemperatureScaleShort)</th>

and use the new method to update the temperate display in the table body.

<td>@fetchDataViewModel.DisplayTemperature(@forecast.TemperatureC)</td>

If we launch our application again the temperate is now displaying in Fahrenheit even though the service returns Celsius. We have used our ViewModel to provide our View with a modified version of the data provided by the Model without altering the original data.

The final requirement we were sent is to allow the user to toggle the displayed temperature from Fahrenheit to Celsius. We’ll keep this simple and just add a button directly to the page to let them toggle this. To support this we will add another property and another method to the ViewModel. The property we will add will just be for displaying the full name of the temperature scale

public string DisplayOtherTemperatureScaleLong

{

get

{

return !_displayFahrenheit ? "Fahrenheit" : "Celsius";

}

}

and the method will just be to toggle the boolean value we created earlier.

public void ToggleTemperatureScale()

{

_displayFahrenheit = !_displayFahrenheit;

}

Once we have pulled everything up to the interface FetchDataViewModel will now look like this:

Now we can go into the View and add in a button that allows us to toggle temperature scale and put it near the top of the page.

<button class="btn btn-primary" onclick=@fetchDataViewModel.ToggleTemperatureScale>Display @fetchDataViewModel.DisplayOtherTemperatureScaleLong</button>

Once this is in place we can launch our application and toggle the temperature display using our new button.

Done for today

And that is it! We have addressed a small shortcoming of our original implementation as well as changing our Model to accept data from a similar but slightly different service. We followed that up with updating our ViewModel and our View to implement new business requirements we received. I hope helps demonstrate the flexibility of this way of implementing MVVM on client side Blazor. I will continue to build on this demo for the time being. In the next article I am planning to have two models be used to implement our next new application feature.

Update: The third article in the series is now published. Click the link below to read it.