MVVM Light Messenger Action Executing Multiple Times

With MVVM Light you can get into a situation where you code-behind's message handler gets called multiple times.

If the ctor for the view is registering for a message then the every time the view loads another subscription will be added; then when the message is sent the are effectively 2 'listeners' which end up executing the registered Action method multiple times.

One solution to this is to make sure you un-register when the view unloads.

The example below shows the code-behind for a simple settings page that registers for a DialogMessage in the ctor, and un-registers when the page is done with.

    public partial class Settings : PhoneApplicationPage
    {
        public Settings()
        {
            InitializeComponent();
            Messenger.Default.Register<DialogMessage>(this, DialogMessageHandler);
        }
        private void DialogMessageHandler(DialogMessage message)
        {
            var result = MessageBox.Show(message.Content, message.Caption, message.Button);
            
            message.ProcessCallback(result);
        }
        private void PhoneApplicationPage_Unloaded(object sender, RoutedEventArgs e)
        {
            Messenger.Default.Unregister(this);
        }
    }

SHARE:

MVVM Light Messenger Events Firing Multiple Times

If you register for a message in the ctor of your views code-behind, eg:

Messenger.Default.Register<DialogMessage>(this, DialogMessageHandler);

Every time you reload the view, i.e by navigating to it, the callback method (in this example DialogMessageHandler) can get called multiple times from the previous times ctor ran.

To fix this all you need to do create an event handler for the PhoneApplicationPage Unloaded and unregister the message (you can unregister more specifically using one of the other overloads):

Messenger.Default.Unregister(this);

SHARE:

Comparing 2 Locations in Windows Phone 7

If you are using Microsoft.Phone.Controls.Maps.Platform.Location in your WP7 application and you want to see if 2 Locations refer to the same place (i.e. the same altitude, latitude and longitude are all equal) then using Location.Equals or == will not work.

This is because Location inherits from Object and doesn't override Equals method, which results in a simple reference equality check.

The extension method below can be used instead:

using Microsoft.Phone.Controls.Maps.Platform;
namespace DontCodeTired
{
    public static class LocationExtensionMethods
    {
        public static bool IsSamePlaceAs(this Location me, Location them)
        {
            return me.Latitude == them.Latitude &&
                   me.Longitude == them.Longitude &&
                   me.Altitude == them.Altitude;
        }
    }
}

 

Example usage:

    [TestFixture]
    public class LocationExtensionMethodsTest
    {
        [Test]
        public void ShouldRecogniseWhenTwoLocationsReferToTheSamePlace()
        {
            var l1 = new Location {Latitude = double.MinValue, Longitude = double.MaxValue};
            var l2 = new Location { Latitude = double.MinValue, Longitude = double.MaxValue };
            Assert.IsTrue(l1.IsSamePlaceAs(l2));
        }
        [Test]
        public void ShouldRecogniseWhenTwoLocationsReferToDifferentPlacess()
        {
            var l1 = new Location { Latitude = double.MinValue - double.MinValue, Longitude = double.MaxValue };
            var l2 = new Location { Latitude = double.MinValue, Longitude = double.MaxValue };
            Assert.IsFalse(l1.IsSamePlaceAs(l2));
        }
    }

 

 

SHARE:

Developing a Windows 7 Phone App That Connects To Azure (a quick overview)

Installing

Download and install VS 2010 RC (phone tools below don't currently work with RTM ver of VS 2010):

http://www.microsoft.com/downloads/details.aspx?FamilyID=301c97f3-aecf-42ca-966a-b8d7304f40b0&displaylang=en

Download and install vs 2010 express for windows phone ctp:

http://www.microsoft.com/express/Downloads/#2010-Visual-Phone

 

Developing

Open VS 2010 RC

New --> Project

Double Click Enable Windows Azure Tools and follow instructions to install Azure tools ( once install starts you will  have to quit VS2010)

 

 

Reopen VS2010

Create new proj Cloud --> Windows Azure Cloud Service


Add WCF Service Web Role

R click Service1 Refactor --> Rename to HelloWorldService

R Click definition for Iservice1 Refactor --> Rename to IHelloWorldService

Change interface and service class to:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

namespace WCFServiceWebRole1
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IService1" in both code and config file together.
    [ServiceContract]
    public interface IHelloWorldService
    {

        [OperationContract]
        string SayHello(string name);     

    }
}





using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

namespace WCFServiceWebRole1
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in code, svc and config file together.
    public class HelloWorldService : IHelloWorldService
    {

        public string SayHello(string name)
        {
            return String.Format("Hello {0}.", name);
        }

    }
}




Add a Windows Phone Application project to the solution.



Create a user interface that looks similar to this (notice how the UI elements are pre-styled to the Win 7 phone look and feel codename 'Metro':



Here's where it gets a bit messy. VS2010 RC phone app project doesn't have an Add Service Reference, so: Save All, then r click Service1.svc --> Preview In Browser, then copy the URL - leave IE open

Open VS 2010 Express, open the solution (there might be some errors, but click ok to them), when the solution opens, add service reference to the Windows Mobile application and paste the URL into the add service box and click ok. Save all and close VS 2010 Express.

Go back to VS 2010 RC and click reload solution if you get prompted.

Now we can double click our button to go to the code behind and type:


        private void button1_Click(object sender, RoutedEventArgs e)
        {
            ServiceReference1.HelloWorldServiceClient proxy = new ServiceReference1.HelloWorldServiceClient();

            // declare callback as statement lambda
            proxy.SayHelloCompleted += (s2, e2) =>
            {
                txtGreeting.Text = e2.Result;
            };

            // call 'Azure' service
            proxy.SayHelloAsync(txtName.Text);

        }

Now hit f5 and wait for the Windows Phone Emulator to start (it may take a little time...) then if u click on the button a keyboard will pop up:



Type you name then click the Say Hello button, you should then see the "Hello ...." result displayed that was returned from the Azure service:


It's pretty amazing that a sole developer can now create a worldwide Win 7 phone app which connects to scalable set of services in Azure all from within VS2010.

SHARE: