206 – Reusable controls

Most reusable controls fall into one of two categories: Custom or composite. A custom control is one where you are doing all the low-level work like rendering. Maybe you need a round gauge with a dial like a speedometer. A composite control is control made up of (composed of, get it?) several other controls. Maybe you use a particular arrangement of a border, label and entry in 10 different places on a page as the form someone fills out. Instead of duplicating the markup 10 times you make a composite control then just place 10 of those on the page. Or maybe you’re tired of the limitations of the built-in header on a navigation page. You could make your own header control then place it on the top of all your pages. In WPF these are UserControl. In Xamarin they are ContentView. Getting used to the naming yet? ContentPage is a page of content, generally views. A grouping of views is the ContentView, which you can then put in other ContentViews or a ContentPage.

Composite controls (ContentViews) are really common, or at least should be, and straightforward to make because you’re not having to do any low-level work. Since they are made from existing controls you know they will render on all the supported platforms. Let’s start with an easy one that everyone needs sooner or later: An input control. You see this everywhere, there is a question or hint, and an entry to type in your value. Maybe it’s for your user name, and another for password. Or for registering on a site for your alias, first name, last name, email address, {…}

If you’re at all like me, you’d rather make something one time and use it many times, than to make it many time – then have maintain every instance individually. So much easier to have it defined in one place, even if it does mean an extra 10 minutes on the front end of the project. There’s that theme again: A little work on the front end saves you tons of work in your day-to-day.

Once done with our new InputControl, you’ll be able to add it to any page and bind to its properties just as easily as any other OEM control

We want this to be a versatile control that you can reuse for all sorts of things. Of course, you can go back and add more and more to it over time to suit your needs; but for now what are the basic properties we probably know we’ll need:

  • Caption – That’s the text that tells us what this is for such as “User Name”, “Password” or “Birthday”
  • Value – That the text the user enters. For the sake of consistency with every other control out there we are not giving it a name like ‘user reply’. Every control has a ‘Value’ and that’s what we all look for and expect when we code.
  • Colors for the caption and the value – both foreground and background


Conceptually that’s all there is to it: A constructor and the properties.

BindableProperty

If you come from WPF this is the Xamarin version of a DependencyProperty. A BindableProperty is basically a normal CLR property with a little bit of plumbing that lets you use it for binding in your XAML views.

A CLR property has a public property with a get and set method, backed by a field, usually set to private.

A BindableProperty also has a public method with get and set, and a backer – only the backer is of type BindableProperty and is created with a method that takes a few parameters such as type, parent type and default value, used to do that plumbing we mentioned.

Your turn

Believe it or not you’ve read everything you need to make all the code-behind for this control. You know the name of the control, the properties we want and have an example. So let’s do it.

Right-click on the Controls folder you made. Choose Add|New Item…

Then select a new Forms Xaml View and name it InputCntrl

Don’t worry about the XAML just yet. We need to make the BindableProperties we intend to bind our UI elements to. We already named them:

And you know the syntax:

I’ll give you the first one to copy/paste. You can type out the rest. (They go in InputCntrl.xaml.cs if you didn’t realize that)

       #region Caption (Bindable string)
        public static readonly BindableProperty CaptionProperty = BindableProperty.Create(
                                                                  "Caption", //Public name to use
                                                                  typeof(string), //this type
                                                                  typeof(InputCntrl), //parent type (tihs control)
                                                                  string.Empty); //default value
        public string Caption
        {
            get { return (string)GetValue(CaptionProperty); }
            set { SetValue(CaptionProperty, value); }
        }
        #endregion Caption (Bindable string)

XAML

Now that you have the properties you can use them in your XAML. Open InputCntrl.xaml

BindingContext is everything when it comes to getting things to bind and work right in any MVVM app – WPF or Xamarin. Controls inherit context from the parent control, unless a different context is explicitly assigned. That’s what we need to do here. We need to tell each UI element (label, entry, button etc.) to explicitly look at this control for its context in order to find those BindingProperties we just made. This is one of the rare occasions when we actually give a XAML element a name: When it is going to be referenced by another XAML element within the XAML itself. To the ContentView, add a tag naming the control ‘this’. That’s right. We’re going to keep to the Microsoft naming and have this item refer to itself as ‘this’. It makes all of us comfortable and the code and markup easy to read and follow.

We can now use ‘this’ as a reference source telling the rest of our XAML where to look for properties to bind to.

I’m sure if you study it a bit you’ll see what’s happening, but for the sake of thoroughness let’s break it down.

  • Style – We defined those earlier so we can keep consistent theme throughout our app.
  • HorizontalOptions & HorizontalTextAlignment – Just to be safe we are overriding these from the style. Remember HorizontalOptions is on the label itself; HorizontalTextAlignment is the position of the text within the label (assuming the label is bigger than it needs to be).
  • Text – Ah… the good stuff. We are binding, referencing ‘this’ as our source. Well, ‘this’ is this control that we just named. On that source of ‘this’ we want to take a path to ‘Caption’ – that’s the BindingProperty we made just a bit ago.
  • TextColor – This looks familiar. We just do the same thing, getting the CaptionForeground property we made from ‘this’ control.
  • BackgroundColor – just like the last two.

Let’s do the same with an Entry. Nothing unfamiliar now:

If we stick those two controls in a Grid of two rows we’re pretty much done with our reusable InputCntrl. I do want to point out that nowhere have we tried to micromanage the size of anything. We aren’t forcing the size of the label… We aren’t hardcoding any numbers anywhere. Our control can size itself as needed. Its seems common sense but lots of people trip over this. For some reason (maybe habit) they just have to try to set the size of everything. That just doesn’t work when you don’t know the size of the phone/tablet/laptop/desktop/watch your app is going to be running on.

Let’s put it to use

If we go back to our MainPage.xaml that we are using for testing we can replace the individual label and entry use for the selected pet’s name with a single control that accepts bindings.
• Comment out the label from the first row, first column.
• Then do the same for the entry in the first row, second column.
• Now add an InputControl in that same space, first row, first column, for a column span of 2
• Bind the value of the InputCntl back to the pet’s name property just the same as we had previously done on the individual Entry.

• Save everything
• Hit [F5] and see it on your device.

Here is a screen capture from an Android tablet. Tap on one of the ListView items. Its details appear on the right for editing… Including in our new reusable control.

205 – Base classes

Let’s be lazy efficient – working smarter instead of harder – through inheritance.

If you’ve done any amount of C# or other OOP language, then you know that inheritance is the mechanism of having one or more classes inherit from a base class. By putting as much common functionality in your base class as possible you don’t have to duplicate it in all the inherited classes. If this is a foreign concept to you then stop and pick up a “Learn C# in 30 days” book and work it cover-to-cover
before going any further because you’ll need those foundation concepts.

We’re going to apply the concept of inheritance to our ViewModels by starting with a ViewModelBase… Well… We’re really going to start even smaller, with a ModelBase class. There will be several things that models and ViewModels have in common such as notifying listeners of property changes. So, we might as well put as much common code in the ‘base-est’ class we can. Then our ViewModelBase will inherit from ModelBase

Reminder: Models are our small data bits. Model = Class = blueprint for an instantiated object = All the same thing. If you’re making a phone book it might be an address class or a person class.

Things that do NOT go in the model or base include:

  • The actual saving and loading from database or file. An object should be ignorant of such things. Its up to the storage/database layer to know the mechanisms of this; not the object.
  • Same goes for network updates. Objects don’t know about sending themselves to a server.
  • Anything to do with the UI. An object doesn’t know a darned thing about the display… or if there even is a display.

Shortly after making the solution, we made folders for Controls, Converters and Icons. We might as well make a couple more right now: Models, ViewModels and Pages.

ModelBase.cs

If you didn’t know this about Visual Studio, its fairly smart and will try to do what it thinks you intended. If you select the folder for Models then choose ‘New Class’ from the context menu (keystroke Shift-Alt-C) it will make a new class for you AND put it in that folder AND give it a namespace path to match. RpxOne.Models.ModelBase.cs Do that now.

Doesn’t look like much right now, does it?

What are some of the things we do with objects, that would go well here?

  • Access them from other classes
  • Serialize them (for an xml file, for network upload, for a local database record etc.)
  • Get notification of changes so our app can react – usually by updating the UI, marking the object dirty so we know to save it before closing, etc.

Lets add support for those things

  1. Access from other classes – So we have to make this class Public
  2. Serializable
    1. We mark the class with the [Serializable] attribute
    2. To be serializable a class must have a constructor that takes no parameters. Add one now.
  3. Notifications to other classes. What do our other classes really want to know about?
    1. When a property changes value – so we can update a label for example
    2. When an object is disposed of,
    3. When the contents of a collection changes – So our ListViews can update. Judging by forum questions this is missed by a lot of people. The question usually sounds like:
      “When my page first comes up the ListView has all the items, but when I add or remove items the ListView doesn’t show the changes. What do I have to do to the ListView to get it to update?” The problem isn’t the ListView: It’s the lack of event notifications on the data bound as the source. The ListView is bound to a Collection property. The property raises a PropetyChangedEvent when the entire property is replaced with a new Collection. If you add one item the Collection is not replaced. That’s where the CollectionChangedEvent comes in.

So lets add inheritance for the interfaces that provide these. At this point your code should look about like this…

and have red squiggles under the interface notations because we haven’t added the required methods to support the interfaces. That’s next.

We’re going to need to raise a couple events for when these changes take place:

The next bit will be a little longer, but not bad. We’re going to add all the methods required by those interfaces. Remember I said at the start of this series that we’re going to do more work up front to make our every day, over and over work easier. This is one of those moments. You will make hundreds of properties in most applications. If an extra few minutes in the base class makes dealing with all of those properties just a minute faster you’ve more than made up for the time spent here. If you need to top off your Mt. Dew, now would be a good time. Go ahead… I’ll wait for ya.

INotifyPropertyChanged

Most intro examples around the ‘net show something like OnPropertyChanged(“FirstName”); because it’s easy to read and doesn’t require the setup we’re about to do. As a result even experienced developers continue to do this for years. Here’s the problem: It violates best practices by using ‘magic strings’. So long as the text in the quotes exactly matches the name of the property you’re golden. But if you (or a team mate) refactor the code so the property becomes “NameFirst” but forgets to look around for all those magical strings all the event notification for this property breaks; and you may not see that right away. It could be on a view that only gets shown when the user has two middle names and a hyphenated last name – or some other one in a thousand case that you don’t check every time you do a quick test. Leading to the update getting released. Three days later support gets flooded with calls from mad customers – Usually resulting in you getting calls on the weekend while you’re trying to relax.

We’re going to create a method in the ModelBase that takes an expression instead of a string and uses that to raise the PropertyChangedEvent. Why an expression? Because that’s what the property itself is. We’re going to send the actual property to this method and let it pull out the name for us. If we can send an expression instead of a string it makes our code easier to read, friendlier to changes, find and replace doesn’t break it, and keeps us from goofing up with typos.

For example this
OnPropertyChanged(() => NameFirst);
is more robust for long term use and maintainability than this
OnPropertyChanged(“NameFirst”);
because if you rename the property you don’t have to search for all
the uses of the magic string “NameFirst”… you don’t have typical human mistakes of typing “FirstName”, “Firstname”, “Namefirst”, “NameFrist” etc.


INotifyCollectionChanged

As mentioned earlier, this is so your classes are notified about changes to elements within a collection, and not just when the entire collection as a whole property is set.

Property – IsDirty

Let’s do one other thing to support this: When ever any property is changed let’s mark the object as dirty. For example, when you change the name of a Person, and the Person is automatically marked dirty, without you having to expressly do it every time on every property of every object.


ViewModelBase : ModelBase

Make a new class in the ViewModels folder and call it ViewModelBase. Just like before, it doesn’t look like much to start with. Make it public, inherit from ModelBase, and serializable.

Hit F6 and make sure everything still builds. We’ve done nothing that should have broken our app, but it costs nothing to double check. You can even hit F5 sending it to your device just to make sure you’re still in a good place. You should still see our very simple starting app that looks similar to this, depending on how much you played with styles etc. earlier.

Testing it

So far this is all theoretical until we actually see it in operation and confirm it all works. In a bit we’ll get into the right way to handle commands and navigating to new pages. But we need these to work first. For now we’re going to use the MainPage for a quick test. We’re going to mock up a PetInfo page, ViewModel to back it with, and of course we’ll need a Pet model. When we’re done it will look like this:

Yes, it is ugly. But it also shows us exactly where every element is from page (red), to ListView (fuscia), to each of the 3 elements in the collection (yellow), to each property on the element (black). I tend to do this sort of thing when I am first making a view because honestly it never goes right the first time and if everything has its own color you can see what you have and what you’re missing, to help point you in the right direction. Later you just take the colors out or make them something more attractive.

  • In the Models folder, make a new Pet class inheriting from ModelBase.
  • Give it properties for
    • Name : string
    • Dob : DateTime
    • Coloring : string
  • In the ViewModels folder, make a new PetsViewModel inheriting from ViewModelBase
  • Give it properties for
    • Pets : ObservableCollection
    • SelectedPet : Pet

So we can have some dummy data add a #if DEBUG block in the constructor to add some values:

#if DEBUG
            Pets.Add(new Pet()
            {
                Name = "Fido",
                Coloring = "Tan",
                Dob = new DateTime(1776, 7, 4)
            });
            Pets.Add(new Pet()
            {
                Name = "Snowball",
                Coloring = "White",
                Dob = new DateTime(1968, 7, 20)
            });
            Pets.Add(new Pet()
            {
                Name = "Santa's Little Helper",
                Coloring = "Brown",
                Dob = new DateTime(1989, 4, 12)
            });
            OnPropertyChanged(()=>Pets);
            NotifyPropertyChanged("Pets");
#endif

To your MainPage code behind we are going to add just one property:
MyViewModel : PetsViewModel

        #region MyViewModel (PetsViewModel)
        private PetsViewModel _MyViewModel = new PetsViewModel();
        public PetsViewModel MyViewModel
        {
            [DebuggerStepThrough]
            get
            {
                if (_MyViewModel == null) MyViewModel = new PetsViewModel();
                return _MyViewModel;
            }

            [DebuggerStepThrough]
            set
            {
                if (_MyViewModel == value) return;
                OnPropertyChanging();
                _MyViewModel = value;
                OnPropertyChanged();
            }
        }
        #endregion MyViewModel (PetsViewModel )

NOTE: This is not how to do things in a finished view, but it will suffice to whack out a quick test. It is NOT an example from MVVM best practices. We’ll cover that in a coming lesson.

Next you need to update the MainPage.XAML to build the UI.  Sadly WordPress is terrible at letting me add XAML in the same way as the CSharp blocks.  There is a big screen capture at the end of this page to show you the XAML.

Now run it on your device!

Play:

Tap on one of the pets in the ListView. Their details populate the right side of the display. If you tap on the name or coloring, you can change it AND IT UPDATES IN THE LISTVIEW IN REAL TIME. That’s the magic of binding – no code behind making explicit updates to various UI fields. The models and view models don’t know a thing about the UI.

Select an item then tap on the DOB field – A DatePicker pops up so you can pick a date. Cool eh?

Source Code

I’m not going to provide full code everyplace. I think there is a lot of learning that takes place when you can’t just copy/paste your way to a completed project. Reading, typeing, debugging, watching Intellisense pop up suggestions, is an invaluable learning process that really drives it all into your brain.

But in this case, since this lesson will be the basis of the follow lessons its important to get it right. So just in case I missed anything during my explanation here’s the full code. (Sorry in advance for how WordPress managles some of this and extends the spacing between lines).

ModelBase.cs

using System;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Xml.Serialization;

namespace RpxOne.Models
{
    [Serializable]
    public class ModelBase : INotifyPropertyChanged,
                             INotifyCollectionChanged,
                             IDisposable
    {
        public ModelBase()
        {
            //Required for serialization
            PropertyChanged += OnPropertyChanged;

        }


        #region Events
        public event NotifyCollectionChangedEventHandler CollectionChanged;
        public event PropertyChangedEventHandler PropertyChanged;
        #endregion Events


        #region Properties
        #region IsDirty
        private bool _IsDirty;
        [XmlIgnore]
        public bool IsDirty
        {
            [DebuggerStepThrough]
            get
            {
                return _IsDirty;
            }

            [DebuggerStepThrough]
            set
            {
                if (_IsDirty == value) return;
                OnPropertyChanging(() => IsDirty);
                _IsDirty = value;
                OnPropertyChanged(() => IsDirty);
            }
        }
        #endregion IsDirty
        #endregion Properties

        #region INotifyPropertyChanged Members
        public static class PropertyHelper
        {
            public static PropertyInfo GetProperty(
                Expression<Func<T, TValue>> selector)
            {
                Expression body = selector;
                if (body is LambdaExpression)
                {
                    body = ((LambdaExpression)body).Body;
                }
                switch (body.NodeType)
                {
                    case ExpressionType.MemberAccess:
                        return (PropertyInfo)((MemberExpression)body).Member;
                    default:
                        throw new InvalidOperationException();
                }
            }
        }
        protected virtual void OnPropertyChanged(Expression e)
        {
            try
            {
                PropertyChangedEventHandler handler = this.PropertyChanged;
                if (handler == null) return;

                // The fully qualified property is really  RpxOne.Models.SomeModel.SomeProperty
                // so we need to strip that down to just the property name.
                var ts = e.ToString();
                var lineage = ts.Split('.');
                if (!lineage.Any()) return;

                var name = lineage[lineage.Length - 1];
                if (name == null) return;

                handler?.Invoke(this, new PropertyChangedEventArgs(name));
            }
            catch (Exception ex)
            {
                //TODO: Log exception
            }
        }
        public void NotifyPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }


        protected virtual void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            try
            {
                IsDirty = true;
            }
            catch (Exception ex)
            {
                Console.WriteLine(string.Format("Error: {0}", ex.Message));
            }
        }

        #endregion INotifyPropertyChanged Members

        #region INotifyPropertyChanging Members
         public event NotifyCollectionChangedEventHandler PropertyChanging;
        protected virtual void OnPropertyChanging(Expression property)
        {
            //PropertyChangedEventHandler handler = this.PropertyChanged;
            //if (handler != null)
            //    handler(this, property.CreateChangeEventArgs());
        }

        #endregion INotifyPropertyChanging Members

        #region IDisposable Members
        [XmlIgnore]
        private bool _disposed = false;

        ~ModelBase()
        {
            OnDispose(false);
        }

        public void Dispose()
        {
            OnDispose(true);
            GC.SuppressFinalize(this);//Prevent redundant call on an already released object.
            //https://msdn.microsoft.com/en-us/library/system.gc.suppressfinalize%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396
        }

        protected virtual void OnDispose(bool disposing)
        {
            string output = String.Format("The Dispose({0}) method.\n", disposing);

            // Execute if resources have not already been disposed.
            if (!_disposed)
            {
                // If the call is from Dispose, free managed resources.
                if (disposing)
                {
                    Console.Error.WriteLine("Disposing of managed resources.");
                    //TODO: Dispose of managed objects
                }
                // Free unmanaged resources.
                output = "Disposing of unmanaged resources.";
                //TODO: Dispose of UNmanaged objects
            }
            _disposed = true;
        }

        #endregion IDisposable Members

        #region OnCollectionChanged Members
        protected virtual void OnCollectionChanged(Expression e)
        {
            var handler = this.CollectionChanged;
            handler?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
        OnPropertyChanged(() => e);//If the contents of the property changed, then the property itself changed as far as binding is concerned. But will cause a listview to reload. Uncomment if you are having issues
        }
        #endregion OnCollectionChanged Member

    }
}</code></pre>
<h3>ViewModelBase.cs</h3>
<pre><code class="language=csharp">using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace RpxOne.ViewModels
{
    [Serializable]
    public class ViewModelBase : Models.ModelBase
    {
        public ViewModelBase()
        {
            
        }
    }
}</code></pre>
<h3>Pet.cs</h3>
<pre><code class="language=csharp">using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;

namespace RpxOne.Models
{
    [Serializable]
    public class Pet : ModelBase
    {
        #region Name (string )
        private string _Name;
        [XmlIgnore]
        public string Name
        {
            [DebuggerStepThrough]
            get
            {
                //if (_Name == null) Name = new string();
                return _Name;
            }

            [DebuggerStepThrough]
            set
            {
                if (_Name == value) return;
                OnPropertyChanging(() => Name);
                _Name = value;
                OnPropertyChanged(() => Name);
            }
        }
        #endregion Name (string )


        #region Dob (DateTime )
        private DateTime _Dob;
        [XmlIgnore]
        public DateTime Dob
        {
            [DebuggerStepThrough]
            get
            {
                //if (_Dob == null) Dob = new DateTime();
                return _Dob;
            }

            [DebuggerStepThrough]
            set
            {
                if (_Dob == value) return;
                OnPropertyChanging(() => Dob);
                _Dob = value;
                OnPropertyChanged(() => Dob);
            }
        }
        #endregion Dob (DateTime )


        #region Coloring (string )
        private string _Coloring;
        [XmlIgnore]
        public string Coloring
        {
            [DebuggerStepThrough]
            get
            {
                //if (_Coloring == null) Coloring = new string();
                return _Coloring;
            }

            [DebuggerStepThrough]
            set
            {
                if (_Coloring == value) return;
                OnPropertyChanging(() => Coloring);
                _Coloring = value;
                OnPropertyChanged(() => Coloring);
            }
        }
        #endregion Coloring (string )
    }
}</code></pre>
<h3>PetViewModel.cs</h3>
<pre><code class="language=csharp">using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
using RpxOne;
using RpxOne.Models;

namespace RpxOne.ViewModels
{
    public class PetsViewModel : ViewModelBase
    {
        public PetsViewModel()
        {
#if DEBUG
            Pets.Add(new Pet()
            {
                Name = "Fido",
                Coloring = "Tan",
                Dob = new DateTime(1776, 7, 4)
            });
            Pets.Add(new Pet()
            {
                Name = "Snowball",
                Coloring = "White",
                Dob = new DateTime(1968, 7, 20)
            });
            Pets.Add(new Pet()
            {
                Name = "Santa's Little Helper",
                Coloring = "Brown",
                Dob = new DateTime(1989, 4, 12)
            });
            OnPropertyChanged(()=>Pets);
            NotifyPropertyChanged("Pets");
#endif
        }

        #region Pets (ObservableCollection )
        private ObservableCollection _Pets;
        [XmlIgnore]
        public ObservableCollection Pets
        {
            [DebuggerStepThrough]
            get
            {
                if (_Pets == null) Pets = new ObservableCollection();
                return _Pets;
            }

            [DebuggerStepThrough]
            set
            {
                if (_Pets == value) return;
                OnPropertyChanging(() => Pets);
                _Pets = value;
                OnPropertyChanged(() => Pets);
            }
        }
        #endregion Pets (ObservableCollection )


        #region SelectedPet (Pet )
        private Pet _SelectedPet;
        [XmlIgnore]
        public Pet SelectedPet
        {
            [DebuggerStepThrough]
            get
            {
                //if (_SelectedPet == null) SelectedPet = new Pet();
                return _SelectedPet;
            }

            [DebuggerStepThrough]
            set
            {
                if (_SelectedPet == value) return;
                OnPropertyChanging(() => SelectedPet);
                _SelectedPet = value;
                OnPropertyChanged(() => SelectedPet);
            }
        }
        #endregion SelectedPet (Pet )
    }
}</code></pre>
<h3>MainPage.xaml.cs</h3>
<pre><code class="language=csharp">using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
using RpxOne.Controls;
using RpxOne.Models;
using RpxOne.ViewModels;
using Xamarin.Forms;

namespace RpxOne
{
    public partial class MainPage : ContentPage
    {
        #region Constructor(s)
        public MainPage()
        {
            InitializeComponent();
        }
        #endregion Constructor(s)


        #region MyViewModel (PetsViewModel)
        private PetsViewModel _MyViewModel = new PetsViewModel();
        public PetsViewModel MyViewModel
        {
            [DebuggerStepThrough]
            get
            {
                if (_MyViewModel == null) MyViewModel = new PetsViewModel();
                return _MyViewModel;
            }

            [DebuggerStepThrough]
            set
            {
                if (_MyViewModel == value) return;
                OnPropertyChanging();
                _MyViewModel = value;
                OnPropertyChanged();
            }
        }
        #endregion MyViewModel (PetsViewModel )
    }
}

MainPage.xaml

Here’s where WordPress really falls down – sorry.  Its hard to present XAML in WordPress because it keeps trying to parse it as part of how the page should be rendered.  Here’s a screenshot of the XAML for making the app page shown above.

mainpage-xaml

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#.