Tuesday, 28 October 2014

INotifyPropertyChanged

The INotifyPropertyChanged interface is used to implement the observable pattern, that is one to many UI Elements can observe the value of a property, and if that property us changed it can updated the values of everything that's observing it.

here's the generic base class I use to implement it

public abstract class BaseModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected bool SetProperty<T>(ref T BackingField, T Value, [CallerMemberName] string PropertyName = "")
    {
        if (object.Equals(BackingField, Value))
            return false;
        BackingField = Value;

        this.UpdateProperty(PropertyName);

        return true;
    }

    protected void UpdateProperty([CallerMemberName] string PropertyName = "")
    {
        if (PropertyChanged != null && !String.IsNullOrEmpty(PropertyName))
            PropertyChanged.Invoke(this, new PropertyChangedEventArgs(PropertyName));
    }
}

it makes life a lot easier rather then setting it up on all your models, just make it once and inherit it where needed.

Wednesday, 15 October 2014

Unit Tests

A unit test, is an automated way to test your code, it takes some getting use to but well worth the effort. for now let's go over how to create a unit test project, a simple test and getting it to work.

don't bother with this go to

https://msdn.microsoft.com/library/hh440545(v=vs.110)#CreateAndRunUnitTestWin8Tailored_Manifest

i only made this post because it cements the procedure in my head.

Let's create a very simple class that takes in two number and adds them together. 

first our award winning UI
<Page
    x:Class="UnitTestExample.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:UnitTestExample"
    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}">
        <StackPanel VerticalAlignment="Center" Margin="100">
            <TextBox Header="First Number:" x:Name="FirstNumber_TXT" />
            <TextBox Header="Second Number:" x:Name="SecondNumber_TXT" />
            <TextBox Header="Answer" x:Name="Answer_TXT" />
            <Button Content="Add" x:Name="Add_BTN" />
        </StackPanel>
    </Grid>
</Page>


with that done let's take a look at our codebehind,

using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace UnitTestExample
{
    public class OurMath {

        public string Add(int A, int B)
        {
            return (A + B).ToString();
        }
    }

    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
            this.Add_BTN.Click += Add_BTN_Click;
        }

        void Add_BTN_Click(object sender, RoutedEventArgs e)
        {
            var a = Convert.ToInt32(this.FirstNumber_TXT.Text);
            var b = Convert.ToInt32(this.SecondNumber_TXT.Text);

            this.Answer_TXT.Text = new OurMath().Add(a,b);
        }
    }
}


Simple enough, now let's test our function, first add a new project and specify a 

with done we should have the following

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;

namespace OurTests
{
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestMethod1()
        {
        }
    }
}

Now before we can actually write any test, we have to make reference to our main project from our test project,

First in your solution explorer right click on the references item and click add reference.


here let's pick our project and hit OK

Now we're ready to rumble, lets rename our test class to OurMathTests and lets rename our test class to TestOurAdd, and add our test statement.

using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
using UnitTestExample;

namespace OurTests
{
    [TestClass]
    public class OurMathTests
    {
        [TestMethod]
        public void TestAddMethod()
        {
            var ourMath = new OurMath();

            Assert.AreEqual(ourMath.Add(5, 4), "9");
        }
    }
}


and that's it, run your test's and all should be well, one thing to remember is that the unit test project also has an app manifest with capabilities that have to be appropriately configured.







Wednesday, 1 October 2014

Message Dialog From ViewModel

In this post I'll demonstrate how I Call a MessageDialog from a ViewModel without using a toolkit

In all apps we need to notify the user of a condition or we need get some information from the user. Now there is a MessageDialog class which makes life much easier for all intensive purposes you can think of it as a message box or an alert. Where the difficulty comes in to play is when you're implementing the Mvvm pattern, where one of the main tenants is the view model should be completely decoupled from the view, that is to say you could potentially swap your view and the view model should not only work but be non the wiser. however this is not the case for the View, it can very much be depended on the viewmodel.

Now recently I came to a problem, I was querying a webservice for some data, but needed to notify the user when there was no connection, so I jumped online and started looking for "Show MessageDialoge using Mvvm" and I got numerous solutions, and they all implement messaging and the mvvm light toolkit, now i'm almost done with my app so to integrate a toolkit now seems a bit silly, so I came up with a different solution.

Instead what i did was create an event handler on the view model that the code behind of the view can subscribe to.

public event EventHandler<MessageDialogEventArgs> ConnectionFailedEvent;

I also created a custom event args model

public class MessageDialogEventArgs : EventArgs
{
    public UICommand CommandOne { get; set; }
    public UICommand CommandTwo { get; set; }

    public string Content { get; set; }
    public string Tite { get; set; }

    public MessageDialogEventArgs() :base()
    { }

    public MessageDialogEventArgs(UICommand CommandOne, string Content, string Title = "")
    {
        this.CommandOne = CommandOne;
        this.Content = Content;
        this.Tite = Tite;
    }

    public MessageDialogEventArgs(UICommand CommandOne, UICommand CommandTwo, string Content, string Title = "")
        : this(CommandOne, Content, Title)
    {
        this.CommandTwo = CommandTwo;
    }


}

this was done for a windows phone 8.1 app in which the message dialog can only have two commands, hence there's only two commands to pass back to the view.

Now in my view model I create the logic to instantiate my event args

// Ensure there's a subsciber to the event
if(this.ConnectionFailedEvent != null)
{
    var mdEventArgs = new MessageDialogEventArgs {
        Content="Cannot retrieve Live data at this time, please check your network connectivity and try again.",
        Tite = "Connection Failure" };

    mdEventArgs.CommandOne = new UICommand("Go Back", c => {
        var frame = ((Frame)Window.Current.Content);

        if (frame.CanGoBack && frame.BackStack.First().SourcePageType == typeof(RoutePage))
            frame.GoBack();
        else
            frame.Navigate(typeof(RoutePage), this.RouteName);
    });
    this.ConnectionFailedEvent.Invoke(this, mdEventArgs);

}

with that done we just have to subscribe to our event in the code behind of our View

//subscribte to the event

this.vm.ConnectionFailedEvent += vm_ConnectionFailedEvent;

now that we've subscribed to our event we just have to implement to invoke logic in our code behind

async void vm_ConnectionFailedEvent(object sender, MessageDialogEventArgs e)
{
    var md = new MessageDialog(e.Content, e.Tite);

    //unsubscribe to our event, for the Garbage Collector
    this.vm.ConnectionFailedEvent -= vm_ConnectionFailedEvent;

    md.Commands.Add(e.CommandOne);

    await md.ShowAsync();

}

one final caveat, you may notice that above we unsubscribe from our event handler, this is done so that the garbage collector can collect this page, when it's not in use. Now we'll also have to unsubscribe from any other places that navigate away from the page, namely the hardware back button.