401 – Revisiting… MVVM

Revisiting some basics

When I started this series, it was my intent to NOT go over the true basics of C# or coding in general. There are so many good tutorials and books and course etc. out there that I didn’t want to rehash all that great material. I also didn’t want to come off sounding arrogant; like I could cover all that better than others had.

But I also said at the start of this series that I was letting the questions on a couple of forums act as my guide for what was needed and wanted. There’s no point covering material that nobody asks questions about, and a disservice to readers to not cover areas that spawn lots of questions.

MVVM – The fundamental design pattern of XAML/C# applications whether WPF or Xamarin

Understand that this is not a comprehensive tutorial on MVVM. There are lots of those and sever good books on the subject. I am not going to insult those authors by suggesting I can cover their material better. Nor am I going to spend my time rehashing material you can readily get directly from those sources.

However, I keep seeing the same question on forums, or the same bad practices on forums again and again. In the end, I choose to think it’s just a case of not knowing they don’t know what they don’t know.

Tiniest of examples from the 30,000ft view.

Let’s say you’re making an HR page that displays information for an `Employee`. You don’t bind to the page’s code behind. Instead you have a `ViewModel` that has properties and method on it all related to working with Employees. Such a `SelectedEmployee` property, `SaveChanges()` method and so on. An individual `Employee` would be a model.

  • MVVM – Model View ViewModel
  • Model – That’s the Employee. It knows nothing more than the employee data. 90% of the time it knows nothing about how it is formatted, viewed, saved… It’s a pure object representing at thing.
  • ViewModel – That’s a group of properties for working with 1-n instances of your Model. Here you have methods for loading your models, selecting one in particular at a time, maybe properties for other models so you can see both the currently selected `Employee` and their `Schedule` and their `JobDescription`.
  • View – That the page or control for interacting with the ViewModel. It has a drop-down for selecting the employee, and a button for [Save] after you make changes.

You set the `SelectedEmployee` on the ViewModel of the page. So your label will show the `.Name` of that employee (Fred Flintstone). When you change `SelectedEmployee`, the label will show the `.Name` of the new model Employee: (Barney Rubble)

`Label.Text` is bound to `SelectedEmployee.name`
If you change the name, the label updates
If you change the selected employee, the label updates

XAML/C#/MVVM concepts and design

There seem to be a lot of people jumping into Xamarin and cross-platform development that have no background in XAML; that did not migrate to Xamarin from WPF. It seems like people are going from 1998 WinForms, skipping over WPF, and straight into Xamarin because they want to get out of positions where there have been held back and into roles that involve the US$ 3 Billion mobile market. Imagine that.

  • First word of advice: Realize that you were held back and that you are skipping over 10+ years in UI advances and design principals. Your WinForms or other platform-specific design patterns DO NOT APPLY any more.
  • Second word of advice: Do not get offended when people say your skills are out of date. You know they are out of date; that’s why you are aiming at Xamarin.
  • Third bit of advice: Do not try to bring your old ways of doing things into the modern world. Do not think you have to learn JUST new ways of building the user interface. There is an entire design pattern and many foundation concepts to be learned when it comes to XAML/C#/MVVM application architecture. If you take the time to learn first and don’t jump right in to trying to architect/design/build your own application your transition will actually be faster.

If you weren’t aware Microsoft created the XAML markup language. XAML/C#/MVVM has been in use for over 10 years. It is not a new thing just for Xamarin. Therefore, there is a LOT more material out there that is meaningful to you than you may have been aware of. Just about everything you read about WPF design principals and concepts applies to Xamarin, at least in a conceptual way. Understanding the relationship between markup and code, between UI and logic & data is vital to building good Xamarin applications. After all, Xamarin is built on top of all that WPF experience as well as ports of the .NET framework.

Basic concept: Separation of UI and logic.

XAML is used to create the User Interface. C# is used to write the logic. The two are NOT supposed to know about each other and certainly DO NOT DEPEND on each other. Under the XAML/C#/MVVM design concept you have something called BindingContext (Xamarin) or DataContext (WPF). BindingContext is a property that tells your XAML where to look for data properties to bind to. When your UI askes for “.Name” or “.Count” this is the object your UI should look at for those values.

Here’s the idea: Your UI can bind to a class that has data and probably some logic. That class is UI agnostic, meaning it doesn’t know or care about how data is presented or even if it is even presented at all.

Your data class should be quite happy running as the backing of a web REST service, backing a console application, a WPF window or a Xamarin Page… even all the above at the same time. Your data classes should not be doing lots of work or holding lots of properties that exist solely for presentation. Do not keep 3 different versions of the same data collection in different sort orders… do not keep 5 different strings just for variants of the date because they are for short form, long form and UTC. Do NOT code directly to UI elements such as textBox4.Text = “Fred”. All of that presentation-specific stuff can be handled differently and better at the point of presentation.

Your UI markup (the XAML) exists for the sole purpose of presenting data. It is a way for your user to interact with your data but it is not the storage of your data. Do not use the labels and textboxes as the places to store values as so many people did (wrongly) in WinForms and other technologies. The UI presents values by binding properties on UI elements with properties in the BindingContext object. For example: A label’s .Text property can be bound to the .Name property of the data object. If the data object is an employee, then the label shows the employee’s name. If the data object is your dog, then the label shows the dog’s name. The important concept to take away from here is that the data class doesn’t know about the UI, and the UI isn’t depended on a specific data class.

Misconception: UI and logic binding is 1:1

It’s very common to see people coding their logic as if there is a one-to-one relationship to UI. For example an EmployeePage and an EmployeePageViewModel. In real-world applications it’s common for the same ViewModel to be the backing for multiple UI/Forms/Pages. For example an EmployeeObject can be the backing for the EmployeeView of the EmployeePage, SupervisorPage and HrPage. It’s the same employee object with the same data, but the HrPage will be able to show the employee’s salary, while the EmployeePage can show the login password and give the employee the ability to change it, and the SupervisorPage shows the employee’s performance review data.

At the same time the SupervisorPage will show different employees’ data by binding to different employee objects. Every time the supervisor selects a new user from a dropdown for example, that employee object becomes the BindingContext of the page causing a complete change in all the data presented to the new employee. No code is executed when that new employee is selected. The UI updates automatically just by the change in BindingContext object. Do I have your attention now?

Thus the relationship of UI to data object is really n:n not 1:1, and is fluid; changing throughout the run-time of the application and not just a one time ‘set-it-and-forget-it’ operation.

Rules of thumb –

  • XAML controls do not get names 99% of the time. If you’re naming controls on a XAML page (or other sub-view) for any reason other than referencing them from another control in XAML you’re probably doing something wrong.
  • Control events such as Button.Click are not to be used for changing other UI elements. Clicking a button should not change whether or not another control is visible for example. Flipping a switch should not change which image is shown. UI elements are binded to data on a ViewModel. Actions/events in the UI trigger actions in the ViewModel such as ‘ProcessImage’ or ‘SaveRecord’. That action might change one or more properties: Maybe a file name is changed, or a status is updated. Since the UI is binded to the data, when the data updates the UI is updated automatically. So there are 3 indirectly associated relations: A control raises a command – the command executes a method on the VM – the method does some work that may as a side affect update some data – the data is binded to some other UI elements so they get updated.
  • If you are subscribing to UI.event then you’re probably doing something wrong. If you’re doing it only for the purpose of something UI related then it might be okay. Button.Click Entry.TextChanged etc. should only be tied only methods in the code-behind the view and should only affect the view and not anything in the program logic. See where we are going with this? Events on UI elements get handled in the code for the UI. The code in the application logic only affects application data. For example: Lets say you’re making a small control that will be reused throughout your application. It could be

Concept: Commands – The next generation of Event

With XAML-based apps comes the concept of ‘Commands’. Think of them as the next evolution of the Event. Commands are less coupled than events. For example, on an event you have to subscribe directly to that instance.
MyClassInstance.SomeEvent += eventHandlerMethod();
Which most times means you have to know the subscription source/target at design time.

But a command can be referenced just by name, including in your XAML binding. Meaning its more fluid and will bind to your context at RUNTIME.

{06dec2017 lost XAML – I’ll try to replace this ASAP}

Commands can also take Parameters that again, don’t have to be defined at design time. You can send virtually any run-time object along with the command, and let the handler be concerned with how to interpret it. In the example above when the command is raised it will carry with it the SelectedDocument as a parameter. So, while you are clicking a button you are not subscribing to the Button.Click then forced to jump through hoops to handle some specific object. Instead the handler for “AcceptThis” receives the actual document to be accepted. The same command handler can then also be assigned to a menu item… Or ListView selection… Or a network call where a document is downloaded and should then be automatically accepted. All of those other options don’t have to know where the command was defined. All of those other options don’t have to provide the same parameter object.

When you put all that together it means an ‘AcceptThisCommand’ can be bound to a photograph in one case and have a photo processor handle it… and bound to a music file in another case and since the handler is from a different context it will know how to handle that data type.

And without the tight binding that events have you can add a new listener FROM the listener without having to know who/where the command is being raise from. You don’t have to to know that the FileDoneDownloadingCommand is buried deep in ApplicationVM.Media.Handlers.REST.Services.Transfers – You just know that you’re listening for the command to be raised. Later when someone refactors that service moving the command to a much easier to remember location all of the subscribers to don’t break. Making it a far more maintainable architecture.

How does that affect your old-school coding habits?
For one: Stop using Button.Click
It’s a hold-over from WinForms days to make the transition easier that brought old habits into new paradigms. Instead you want to assign a command to your button. Your thinking should be more “What is the purpose of the button?” and less “What method do I execute from the button?” The purpose of the button is to tell your app that something has happened, and less about micromanaging what to do when it happens.

Concept: Converters

XAML apps make heavy use of Converters for presentation purposes. Let’s say you’re building a rocket science program. Your model assumes your rocket speed is measured in meters-per-second. But for your display you’d like to show something more human friendly like Miles per Hour. Instead of making a second property on your data object, or cramming in the match on the data object we’ll make a converter that does this. That way we can re-use the converter in countless places rather than have countless property or numerous duplications of our math.

Now we can use binding to grab the speed off our rocket object and display it as MPH with one line:

{06dec2017 lost XAML – I’ll try to replace this ASAP}

Notice how we even assigned a StringFormat in there to limit the value displayed to only two decimal places. Again, we aren’t creating more properties just for formatting the value. Formatting is just for presentation purposes and has nothing to do with the actual logic of the object so we keep it in the XAML and out of the C#.

4 thoughts on “401 – Revisiting… MVVM

  1. If I may, it would be really helpful for you to break down the development process for a basic application. I don’t know XAML and have picked up a lot from Microsoft Virtual Academy’s walkthrough of XAML and App Studio. Their totorial went something like Setup> The work environment> Making your first App (hello world)> Coding layouts in XAML > Navigation w/ XAML. There were small tests/challanges sprinkled in to test knolegde and those were super helpful.

    • Thank you for taking the time to not only view the site but to reply. I know it takes times and I appreciate the feedback as it helps craft the direction to take.
      A few aspects of my blog I hope you’ll consider.

      This is a one-man blog, not a corporate driven site with a vast team. The content here is all created by me, after working my full-time Sr. Developer/Project Lead position. On the minus side it means there aren’t 10 updates a day. On the plus side it is all based on two decades of real experience from the same person. Every article is told with the same voice, from the same perspective, with the same goal. Hopefully giving the site good cohesion.

      I actually am following those same steps to a degree. I hope you noticed that all the 100 series articles are about setup> Work environment and so on. Hopefully the depth of each article is a bit more, or touches on elements not commonly covered. For example, I don’t see other sites advocating how multiple monitor workstations help you be more productive. My goal is to help bring some of that real work place experience. A side effect of that depth is that the articles take more time to create.
      The 200 series is my “Making your first App”. Except I’m not doing it as a one-off half hour lesson. I’m showing the approach of doing more work up front – BUT – Explaining the *why* and thought process of these decisions and how they affect big-picture aspects of software like long-term maintainability over a decade or in a 20 person team setting. You don’t see those things touched on much elsewhere.

      There are a thousand sites that will show you how to slam together “Hello World”. If I make number 1,001 it doesn’t bring anything new to the table. I know when I was transitioning from rookie to series amateur-hobbyist one of the biggest problems I had was finding new material that wasn’t a re-hash of the same ‘introductory’ books and articles. That’s what I’m aiming to create here. I am not interested in making the next clone of every other beginner site. I want to create a site for those readers to come to when they are ready to move on and do more interesting things… When they have realized the tiny self-contained 20 minute lessons don’t apply to medium-to-large scaleable projects… When those students want to gain the NEXT LEVEL skillset that can get them promoted from intern or Developer 1 to Sr. Developer.

      I also realize that there is an entire internet out there. I am not trying to pretend that mine is the only site someone can learn at. I don’t want it to be. I want people to hit 100 other sites… learn those basics anywhere and everywhere… take those MSVA tests… watch those UDemy videos… Then come here and learn how to put it all together in a meaningful and thought-out way. I want to help people transition from ‘coder’ doing what they’re told to “developer’ to ‘architect’ doing the big-picture planning and telling the coder what their part is. I’m fine with other sites teaching people how to make the bricks if they come here to learn how to plan and build a house.

      Lastly… I’m not trying to obtain high numbers of visitors. I’m not reaching out for half a million likes: Those and $8 still get me a frappicino. I’m more interested in making a difference to how 100 people code if it helps them improve how they plan and the quality of their code, because I know that will have a direct affect on the quality of their employment, and thus improve their quality of lifestyle. Quality over quantity. I’d rather make a meaningful impact on 100 people than to brag about 100,000 page hits.

      Hopefully its the differences between Red Pill Xamarin and other “Build ‘Hello World’ ” sites that will keep you coming back – and keep you participating and interactive.

      • Thanks so much for the response. As someone who is self taught and in a space between “hacker”, “coder”, and “developer”, I really do appreciate the care you’re taking to really explain the why as well as the what. It gives insight into the design mentality one has to take when approaching the creation of a successful and scalable application that I haven’t been able to find anywhere else online yet.

        I’ve been looking for a way to learn and understand Xamarin (that I can afford) that I haven’t been able to find elsewhere online. And you’re blog has been so helpful thus far that I was hoping you would be able to fill in the gaps as you go, or at least point me in that direction. I forgot that you explicitely said that was not your intention in making the blog in your introduction. I guess I’l have to keep searching, and in the meantime I’ll have your blog open while as I learn the ins and outs of cross-platform development with Xamarin.

Comments are closed.