So, full disclosure, I’m a Microsoft guy.  I make far more money immersing myself into Windows development than I would in developing for any other platform.  There’s good reason for this, but that’s a topic for a different article.

What are they?

Windows 10 is a general purpose operating system.  You can do just about anything with it.  Want to host a personal website?  Done.  Want to develop for your hobbies?  Done.  Want to do serious work?  Done.  Want to play games?  Done.  Windows 10 is the best iteration of Windows to date and the breadth and depth of usages for Windows 10 is beyond compare.

Android-x86 is an end-user operating system.  You can do many things with it, mostly surrounding social interaction, casual gaming, and light business applications.  It’s also a pretty good platform for general web activities as Chrome on Android is just as good as Chrome on Windows.  What it’s not is a serious OS for developing software or hosting your favorite game server.

If they are so different, why the comparison?

I am limiting this comparison to end-user scenarios: Browsing, casual gaming, and social interaction.  I’m also ignoring hardware specifically designed for Android or Windows 10.  Instead, I’m using a neutral platform, a Dell Inspiron laptop.

All the formalities aside, let’s get started.

Browsing

Chrome is available for both operating systems.  The experience with Chrome is nearly identical.  As far as performance, Chrome on Android seems faster than it does on Windows.  This is probably because Chrome does all kinds of funky things on Windows to try to be an operating system inside an operating system.  On Android everything is already an OS inside an OS, so Chrome is a lot lighter than it is on Windows.  An Universal Windows App version of Chrome would be way better than the current desktop version and would probably trounce Chrome on Android in performance as UWP apps are typically written in C++ or CSharp, both of which are light-years ahead of Java in performance.

Social Interaction

Now, I’m only going to compare apps, not websites.  Some apps are not available on Windows 10 because their Website performance is so good (generally because the hardware for Windows 10 is 10x faster than Android products).  This is a mistake from my perspective, because websites are much harder to develop (if you want to know why, leave a comment and I’ll explain).

The elephant in the room is the respective Facebook apps.  Here, there’s no comparison.  The Android Facebook app is quite possibly the best app on Android, period.  It’s the most fully featured, usable and well thought out app anywhere.

In comparison, the Facebook UWP app absolutely sucks.  It’s tempermental, lacks features and sometimes won’t do simple things like showing the notifications.  I don’t know if this is intentional, but it sucks.

Facebook has published some interesting apps for managing your Facebook pages and advertising campaigns, but they are only available on Android (maybe iOS, but who cares?).

Next is Twitter.  Unlike Facebook, Twitter seems to keep their Android and UWP apps pretty much synced up in both functionality and performance.  I suspect they are using a common C++ code base which means it’s a lot easier for them to keep things in sync.  It’s also nowhere near as fat as the Facebook app on either platform, but it doesn’t need to be as it’s a much simpler set of functionality.

The final app I’ll compare is IRC Cloud.  Wait, I cannot.  IRC Cloud doesn’t have a UWP app.  Nevermind.  This is another case where the Website is seen as the primary channel for usage and thus a stand-alone USP app is ignored.

Gaming

When it comes to gaming, Windows 10 absolutely trounces Android.  There’s simply no comparison.  Even limiting yourself to UWP games, they are typically better, more fully featured, and perform better than any equivalent Android app.  Just go to the Windows store.  The highest rated apps are all games, and for good reason.

From a social perspective, the XBOX apps on Windows and Android echo the gaming experience overall.  The XBOX app built into Windows 10 is phenomenal.  Every little bit of social interaction available on XBOX is here.  You can even broadcast your Windows 10 gaming sessions to your channel, just like you can on the XBOX One.  The XBOX One app for Android is essentially a remote control with a few simple features that don’t do much.

Even when Android and Windows both have the same game, the Windows version is typically better.  Remember that 10x more powerful hardware thing?  That makes a big difference for publishers when deciding what type of games and how to code them.  Many, many, many games on Android are built with Unity, and if you build a game with Unity, it’s a no brainer to target UWP, XBOX One, and Android in one fell swoop.  Android x86 narrows the gap a bit, but Windows 10’s graphics drivers are so good, that you still get a better gaming experience on Windows 10.

Conclusion

It’s a tie.  You really have to decide what your main usage for a computer is to decide which way to go.  If browsing the web and reading email is your thing, then you can’t go wrong with either Android or Windows 10.  If you want native apps for social media, then Android trounces Windows 10, unless you limit your social media experience to Twitter, at which point it’s a tie.  Finally, Windows 10 owns gaming.  There’s really nothing else to say about that.

Of course, there’s some philosophical differences when choosing between Windows 10 and Android x86.  If you’re a Microsoft Guy, you cannot go wrong with Windows 10.  There’s nothing about Android apps that either isn’t matched in a UWP app, or a website.  If you have needs beyond those covered here, you’re probably going to be better off with Windows 10.

If you are an Open-Source, or anti-Microsoft Guy, then Android-x86 is for you.  You’ll be more than satisfied with the apps available through the Google Play Store, and most really benefit from the faster hardware.  If you’re a power user in this category you’ll probably dual boot Android and a more traditional GNU/Linux system such as an Ubuntu variant.

Android-x86 is what Chromebook should have been.

INTRODUCTION: Over a two part series I introduced how to use an MVC pattern with a Universal Windows App.  That example simply gave a list of Game of Thrones characters for display.  I’ve extended the example to also allow editing those characters in a details page.  I’ve also added a singleton to control application state and to perform navigation.

Let’s first take a look at the Singleton, which I’ve named ApplicationSingleton.  I’ve moved the instantiation of the Controller to this class as well as removed code in App.xaml.cs that used the Frame.  Instead of a navigation frame, our Singleton will assign instances of MainPage and DetailsPage to the Window Context as the user navigates the app.

EXAMPLE: App.xaml.cs Changes

        /// <summary>
        /// Invoked when the application is launched normally by the end user.  Other entry points
        /// will be used such as when the application is launched to open a specific file.
        /// </summary>
        /// <param name="e">Details about the launch request and process.</param>
        protected override void OnLaunched(LaunchActivatedEventArgs e)
        {

#if DEBUG
            if (System.Diagnostics.Debugger.IsAttached)
            {
                this.DebugSettings.EnableFrameRateCounter = false;
            }
#endif

            Window.Current.Content = ApplicationSingleton.Instance.MainPage;
            Window.Current.Activate();
        }

Now that we have the App setting it’s initial page with the Singleton, we’ll take a look at the Singleton itself.

EXAMPLE: ApplicationSingleton Code

using System.Collections.Generic;
using Windows.UI.Xaml;
using SharpNinja.Controllers.People;
using SharpNinja.Models.BlogEntities;
using SharpNinja.Utilities.MvcBasics;

namespace SharpNinja.UI.Windows10Sample2.Singletons
{
    internal class ApplicationSingleton
    {
        private ApplicationSingleton()
        {
            _personsController.Initialize(new List<IView> { _listView, _detailsView });
        }

        private readonly static ApplicationSingleton _instance = 
            new ApplicationSingleton();

        public static ApplicationSingleton Instance => _instance;

        private readonly PersonsController _personsController = 
            new PersonsController();

        private MainPage _listView = new MainPage();
        public MainPage MainPage => _listView;

        private DetailsPage _detailsView = new DetailsPage();
        public DetailsPage DetailsView => _detailsView;

        private AppState _state = AppState.List;

        public void Navigate(AppState state, params object[] values)
        {
            switch (state)
            {
                case AppState.List:
                    Window.Current.Content = _listView;
                    _state = AppState.List;
                    break;

                case AppState.Details:
                    Window.Current.Content = _detailsView;
                    var person = values[0] as Person;
                    _detailsView.InvokeLoadPersonModel(person.Name);
                   _state = AppState.Details;
                    break;
            }
        }
    }

    internal enum AppState { List, Details }
}

The Singleton is used to not only manage the state of the application, but to instantiate and register the pages of the application with the PersonsController (which has not changed at all to accomodate the changes in the User Interface).

The MainPage had to be updated a little to handle the SelectedItemChanged event so that users can click a character and open their details.

EXAMPLE: MainPage.xaml Changes

        <ListView Name="lstResults" Grid.Row="1" HorizontalAlignment="Stretch"
                  SelectionChanged="Selector_OnSelectionChanged">

EXAMPLE: MainPage.xaml.cs Changes

        private void Selector_OnSelectionChanged(object sender, 
            SelectionChangedEventArgs e)
        {
            if (e.AddedItems.Count == 1)
            {
                var person = e.AddedItems[0] as Person;

                ApplicationSingleton.Instance.Navigate(AppState.Details, person);
            }
        }

We now have our navigation and MainPage changes.  We can now look at the XAML for our DetailsPage.

EXAMPLE: DetailsPage.xaml Code

<Page
    x:Class="SharpNinja.UI.Windows10Sample2.DetailsPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:SharpNinja.UI.Windows10Sample2"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" 
    >
    <Page.TopAppBar>
        <AppBar Height="50" Background="Black" IsOpen="True">
            <AppBarButton Height="50" Name="btnBack" Click="ButtonBase_OnClick">
                <TextBlock Margin="5 0 5 0">Back</TextBlock>
            </AppBarButton>
        </AppBar>
    </Page.TopAppBar>
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <Border Grid.Row="0" BorderThickness="5" CornerRadius="7" 
                Background="Blue" BorderBrush="Yellow" 
                Margin="10 5 10 7" Padding="8" Name="nameBorder">
            <TextBlock Text="{Binding Name, Mode=OneWay}"/>
        </Border>

        <Grid Grid.Row="1" Margin="10 5 10 7">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>
            <TextBlock Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="5 0 5 0">First Name:</TextBlock>
            <TextBox Grid.Row="0" VerticalAlignment="Center" Grid.Column="1" Text="{Binding FirstName, Mode=TwoWay}"/>
            <TextBlock Grid.Row="1" VerticalAlignment="Center" Grid.Column="0" HorizontalAlignment="Left" Margin="5 0 5 0">Last Name:</TextBlock>
            <TextBox Grid.Row="1" VerticalAlignment="Center" Grid.Column="1" Text="{Binding LastName, Mode=TwoWay}"/>
            <TextBlock Grid.Row="2" VerticalAlignment="Center" Grid.Column="0" HorizontalAlignment="Left" Margin="5 0 5 0">Date of Birth:</TextBlock>
            <DatePicker Grid.Row="2" VerticalAlignment="Center" Grid.Column="1" Date="{Binding DateOfBirth, Mode=TwoWay}"/>
            <TextBlock Grid.Row="3" VerticalAlignment="Center" Grid.Column="0" HorizontalAlignment="Left" Margin="5 0 5 0">Age:</TextBlock>
            <TextBlock Grid.Row="3" VerticalAlignment="Center" Grid.Column="1" Text="{Binding Age, Mode=OneWay}"/>
        </Grid>
        <Border Grid.Row="2" BorderThickness="5" CornerRadius="7" 
                Background="Blue" BorderBrush="Yellow" 
                Margin="10 7 10 7" Padding="8" Name="statusBorder">
            <TextBlock Name="lblStatus"/>
        </Border>

    </Grid>
</Page>

EXAMPLE: DetailsPage.xaml.cs Code

using System;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
using SharpNinja.Controllers.People.Views;
using SharpNinja.Models.BlogEntities;
using SharpNinja.UI.Windows10Sample2.Singletons;

namespace SharpNinja.UI.Windows10Sample2
{
    public sealed partial class DetailsPage : Page, IPersonDetailsView
    {
        public DetailsPage()
        {
            this.InitializeComponent();
        }

        private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
        {
            ApplicationSingleton.Instance.Navigate(AppState.List);
        }

        // From IView 
        public void SetStatus(string message, bool isError)
        {
            lblStatus.Text = message;
            statusBorder.Background =
                new SolidColorBrush(isError ? Colors.Red : Colors.Blue);
        }

        public Person Model { get; set; }
        public event EventHandler<string> LoadPersonModel;

        internal void InvokeLoadPersonModel(string name)
        {
            LoadPersonModel?.Invoke(this, name);
            DataContext = Model;
        }

    }
}

The DetailsPage uses two way binding on the Model property (an instance of the Person object defined in the IPersonDetailsView interface).  This allows the UI and Model to be updated in real time.  Because the List page uses the ObservableCollection to hold all of the instances of the Person object, even the MainPage gets updated so when you go back to it, you see the changes immediately without having to refresh the search!

CONCLUSION: Using the MVC pattern along with a Singleton is a very, very powerful method of engineering any application.  Here we see it working beautifully with a Universal Windows Application, but it could just as well be WinForms or ASP.Net.  MVVM is not the end-all-be-all of XAML-based development.  Whether you are using Silverlight, WPF, Windows Store App, or Universal Windows App, you can still use the tried and true MVC, and you get a more portable framework to boot.

INTRODUCTION In part one of this series we built a simple MVC framework for our GoT character search engine. Now let’s look at how we can expand it actually provide a user interface via a Windows 10 Universal App. BTW, all of the code for this app is on GitHub.

We’ve already defined the first interface for our app, IPersonListView in the previous article.

Now we’ll implement that view with our MainPage of our search engine app.

EXAMPLE 1

using System;
using System.Collections.ObjectModel;
using System.Linq;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
using SharpNinja.Models.BlogEntities;
using SharpNinja.UI.Windows10Sample.Controllers;
using SharpNinja.UI.Windows10Sample.Views;

namespace SharpNinja.UI.Windows10Sample
{
    public sealed partial class MainPage : Page, IPersonsListView
    {
        // Our controller
        private PersonsController _controller = new PersonsController();

        public MainPage()
        {
            this.InitializeComponent();

            // Initialize the controller
            _controller.Initialize(new []{this});
        }

        // From IView 
        public void SetStatus(string message, bool isError)
        {
            lblStatus.Text = message;
            statusBorder.Background = 
                new SolidColorBrush(isError ? Colors.Red : Colors.Blue);
        }

        // The Persons list
        public ObservableCollection<Person> PersonsList { get; set; }

        // Tells the controller to find the persons based on the 
        // provided partial string.
        public event EventHandler<string> FindPersons;

        // Bind the results;
        public void BindPersonsList()
        {
            // Views are responsible for sorting data
            // based on user preferences.
            lstResults.ItemsSource = 
                new ObservableCollection<Person>(
                    PersonsList.OrderBy(x => x.Name));
        }

        private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
        {
            // Use null propagation to invoke our search.
            FindPersons?.Invoke(sender, txtSearchTerm.Text);
        }
    }
}

Here’s the XAML…

EXAMPLE 2

<Page
    x:Class="SharpNinja.UI.Windows10Sample.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:SharpNinja.UI.Windows10Sample"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <Border Grid.Row="0" BorderThickness="5" CornerRadius="7"
                Background="DarkBlue" BorderBrush="Yellow" 
                Margin="10 7 10 7" Padding="8">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="Auto" />
                </Grid.ColumnDefinitions>
                <TextBlock Grid.Column="0">Search Term</TextBlock>
                <TextBox Grid.Column="1" Name="txtSearchTerm"/>
                <Button Grid.Column="2" Click="ButtonBase_OnClick">GO!</Button>
            </Grid>
        </Border>
        <ListView Name="lstResults" Grid.Row="1" HorizontalAlignment="Stretch" >
            <ListView.ItemTemplate>
                <DataTemplate>
                    <Grid HorizontalAlignment="Stretch">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto"/>
                            <ColumnDefinition Width="20" />
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>
                        <TextBlock Grid.Column="0" 
                                   Text="{Binding Path='Age', Mode=OneWay}" />
                        <TextBlock Grid.Column="2" 
                                   Text="{Binding Path='Name', Mode=OneWay}" 
                                   HorizontalAlignment="Stretch"/>
                    </Grid>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
        <Border Grid.Row="2" BorderThickness="5" CornerRadius="7" 
                Background="Blue" BorderBrush="Yellow" 
                Margin="10 7 10 7" Padding="8" Name="statusBorder">
            <TextBlock Name="lblStatus"/>
        </Border>
    </Grid>
</Page>

In future articles I’ll spend more time on this example and how all of the databinding works, but for now know that the basic flow is that the user types some text to search for, clicks “GO” and then the controller finds the matching Persons and tells the View to bind to it.

CONCLUSION: Really that’s about it for the search engine. In the next post in this series we’ll look at extending the application to include a second page for entering or editing people.

INTRODUCTION: Previously, I wrote about the MVC design pattern.  That article focused on the mechanics of the pattern more than a realistic implementation.  In this article we’ll look at a full MVC application, starting with the Model, the Controller and finally the Views as implemented in a Windows 10 Universal Application.

THE MODEL: For this application we’ll use a fairly complex Person class that has normal CRUD properties as well as some data-centric properties such as calculating age from the Date of Birth property.  This will give you a good idea of the kind of classes you can make for serialization using your preferred format (SOAP, JSON, Binary, etc).

EXAMPLE 1 – THE PERSON CLASS

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

namespace SharpNinja.Models.BlogEntities
{
    [DataContract]
    public class Person : INotifyPropertyChanged
    {
        private string _firstName;
        private string _lastName;
        private DateTime _dateOfBirth = DateTime.Today;

        public Person(string firstName, string lastName)
        {
            FirstName = firstName;
            LastName = lastName;
        }

        [DataMember]
        public string FirstName
        {
            get { return _firstName; }
            set
            {
                if (value == _firstName) return;
                _firstName = value;
                OnPropertyChanged();
            }
        }

        public string Name => $"{FirstName} {LastName}";

        [DataMember]
        public string LastName
        {
            get { return _lastName; }
            set
            {
                if (value == _lastName) return;
                _lastName = value;
                OnPropertyChanged();
            }
        }

        [DataMember]
        public DateTime DateOfBirth
        {
            get { return _dateOfBirth; }
            set
            {
                if (value.Equals(_dateOfBirth)) return;
                _dateOfBirth = value;
                OnPropertyChanged();
                OnPropertyChanged(nameof(Age));
                OnPropertyChanged(nameof(IsChild));
            }
        }

        public int Age => (DateTime.Today - DateOfBirth).Days / 365;

        public bool IsChild => Age < 18;

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

The Person class has a lot of nifty features. It implements INotifyPropertyChanged so that views that are databinding capable are able to bind to the values of the Person. Another feature is that it’s marked as a DataContract which allows it to be easily serialized. The properties representing the serializable content are also decorated with the DataMember attribute.

Just a quick note… See that method invocation of PropertyChanged? That’s the correct way to call an event using Null Propagation.

VIEWS PART 1: Our Person Model now needs to be interacted with in some way. There are two main use cases for our application: get a list of Person instances and editing a Person. For this tutorial we will focus on getting the list of Person instances by create a simple search engine for Game of Thrones characters.

The view for the search engine will define a list of Person objects, an event for telling the Controller that a search is required, and a callback method for the Controller to let the View know that new results are ready.

EXAMPLE 2

using System;
using System.Collections.ObjectModel;
using SharpNinja.Models.BlogEntities;
using SharpNinja.Utilities.MvcBasics;

namespace SharpNinja.UI.Windows10Sample.Views
{
    public interface IPersonsListView : IView
    {
        ObservableCollection<Person> PersonsList { get; set; }

        event EventHandler<string> FindPersons;

        void BindPersonsList();
    }
}

That’s all that’s necessary to define the View, and that’s all that’s necessary to implement the Controller.

BTW, all of the source code for this article (and the next one) is located on GitHub. You will see some code there that’s not 100% pertinent to this article.

THE CONTROLLER: The Controller is the heart of the application. It is responsible for persisting and retrieving Models from the data store, for enforcing the rules of the application, and for providing non-UI oriented logic. In our app, the Controller will act as the search engine, accepting a partial match string as a parameter for the FindPersons event of the IPersonsListView.

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using SharpNinja.Models.BlogEntities;
using SharpNinja.UI.Windows10Sample.Views;
using SharpNinja.Utilities.MvcBasics;

namespace SharpNinja.UI.Windows10Sample.Controllers
{
    public class PersonsController : IController
    {
        private List<Person> _fakePersonsDatabase;

        public PersonsController()
        {
            _fakePersonsDatabase = new List<Person>();

            _fakePersonsDatabase.Add(new Person("John", "Snow") { DateOfBirth = new DateTime(1995, 2, 28) });
            _fakePersonsDatabase.Add(new Person("Ned", "Stark") { DateOfBirth = new DateTime(1971, 1, 15) });
            _fakePersonsDatabase.Add(new Person("Stannis", "Barathian") { DateOfBirth = new DateTime(1952, 12, 8) });
            _fakePersonsDatabase.Add(new Person("Aria", "Stark") { DateOfBirth = new DateTime(2003, 7, 10) });
        }

        #region IDisposable
        protected bool _isDisposed = false;
        public void Dispose()
        {
            if (!_isDisposed)
            {
                // Dispose of resources

                _isDisposed = true;
            }
        }
        #endregion

        #region Views
        private readonly List<IView> _views = new List<IView>();
        private IPersonsListView _personsListView = null;

        protected IPersonsListView PersonsListView
        {
            get
            {
                return _personsListView ??
                       (_personsListView = _views.FirstOrDefault(x => x is IPersonsListView) as IPersonsListView);
            }
        }
        #endregion

        public void Initialize(ICollection<IView> views)
        {
            foreach (var view in views)
            {
                if (view is IPersonsListView &amp;&amp; !_views.Any(x => x is IPersonsListView))
                {
                    _views.Add(view);

                    PersonsListView.FindPersons -= PersonsListViewOnFindPersons;
                    PersonsListView.FindPersons += PersonsListViewOnFindPersons;
                }
            }
        }

        private void PersonsListViewOnFindPersons(object sender, string s)
        {
            if (PersonsListView != null)
            {
                var search = s.ToLower();
                var results =
                    _fakePersonsDatabase.Where(
                        x => x.FirstName.ToLower().Contains(search) || x.LastName.ToLower().Contains(search)).ToList();

                if (results.Count > 0)
                {
                    PersonsListView.PersonsList = new ObservableCollection<Person>(results);

                    PersonsListView.BindPersonsList();
                    PersonsListView.SetStatus($"Found {results.Count} persons matching {s}", false);
                }
                else
                {
                    PersonsListView.SetStatus($"No results found for {s}.", true);
                }
            }
        }
    }
}

There’s a lot going on here, so let’s start at the top. Our application implements a fake datastore of GoT characters. This is not typical of a real app, but I didn’t want to introduce database code into this first example.

Next, you will see a property named PersonsListView. This property makes it possible to use a strongly typed instance of the View while only having to do the type checking once.

Our compulsary Initialize method adds IView instances to the controller. It knows about the events exposed in the View and appropriately registers to those events.

Finally, our event handler method does the searching of the fake datastore and places the data in the View’s PersonsList and invokes the View’s BindPersonsList call-back method.

STOPPING POINT:  That’s enough for this article.  The next article will bring it all together into a Windows 10 Universal App.  See you then!