22 February 2012

Behavior to show a MessageBox from a ViewModel

Since I am a very lazy programmer and I not always want to register or define services and whatnot for showing a simple message I created this extremely simple behavior for showing a MessageBox from a ViewModel. I wrote the code for Windows Phone 7, but I suppose it could be used in Silverlight as well.

The behavior itself is as simple as this:

using System.Windows;
using System.Windows.Interactivity;

namespace Wp7nl.Behaviors
{
  public class MessageBoxDisplayBehavior : Behavior<FrameworkElement>
  {
    public const string MessagePropertyName = "Message";

    public string Message
    {
      get { return (string)GetValue(MessageProperty); }
      set { SetValue(MessageProperty, value); }
    }

    public static readonly DependencyProperty MessageProperty =
      DependencyProperty.Register(
        MessagePropertyName,
        typeof(string),
        typeof(MessageBoxDisplayBehavior),
        new PropertyMetadata(string.Empty, MessageChanged));

    public static void MessageChanged(DependencyObject d, 
      DependencyPropertyChangedEventArgs e)
    {
      var msg = e.NewValue as string;
      if (!string.IsNullOrEmpty(msg))
      {
        MessageBox.Show(msg);
      }
    }
  }
}

Easiest way to use it is to just drag it onto about any control in your Page using Blend, as long as it has the right data context, and select a string property to bind it to. In XAML, it usage looks something like this:

<Grid DataContext="{Binding ChooserViewModel}">
 <i:Interaction.Behaviors>
  <Wp7nl_Behaviors:MessageBoxDisplayBehavior 
    Message="{Binding MessageBoxMessage, Mode=TwoWay}"/>
 </i:Interaction.Behaviors>

Just one the one thing you might want to consider is how you define “MessageBoxMessage” in your ViewModel. I defined it as follows:

private string messageBoxMessage;
public string MessageBoxMessage
{
  get { return messageBoxMessage; }
  set
  {
    messageBoxMessage = value;
    RaisePropertyChanged(() => MessageBoxMessage);
  }
}
as opposed to what you would normally do, which is
private string messageBoxMessage;
public string MessageBoxMessage
{
  get { return messageBoxMessage; }
  set
  {
    if (messageBoxMessage != value)
    {
      messageBoxMessage = value;
      RaisePropertyChanged(() => MessageBoxMessage);
    }
  }
}
I intentionally left out the value check (in red), so RaisePropertyChanged always fires. This gives the real stupid mentally challenged users that make the same error multiple times multiple message boxes as well ;-)

06 February 2012

JSON deserialization with JSON.net: class hierarchies

In part 1 of this series I described the basics of creating classes from a JSON string and then simply deserializing the string into a (list of) classes. That way, you don’t have all the hooplah of SOAP, but still have strongly-typed classes in your client app. But beware, there is no formal contract either, so on a beautiful morning you might start to think that either you had too much of a drink yesterday evening, or that the company providing the data feed for your app indeed has started to sell Windows Phone 7 devices made by Sony, with a 65” screen.

Looking at the JSON string you now see something like this:

[
  {
    "Brand": "Nokia","Type" : "Lumia 800", "Device" : "Phone",
    "Specs":{"Storage" : "16GB", "Memory": "512MB","Screensize" : "3.7"}
  },
  {
    "Brand": "Sony", "Type" : "KDL-65HX920","Device" : "TV",
    "Specs":{"Screensize" : "65", "FullHD" : "Yes", "ThreeD" : "Yes" }
  },  
  { "Brand": "Nokia","Type" : "Lumia 900","Device" : "Phone",
    "Specs":{"Storage" : "8GB", "Memory": "512MB","Screensize" : "4.3" }
  },
  {
    "Brand": "Samsung", "Type" : "UE55C9000","Device" : "TV",
    "Specs":{"Screensize" : "55", "FullHD" : "Yes", "ThreeD" : "Yes" }
  },  
]
None of the two options mentioned before appear to be true: apparently the company has diversified. They are now selling TV's as well. Of course you could run this trough json2csharp, which will give you this:
public class Specs
{
    public string Storage { get; set; }
    public string Memory { get; set; }
    public string Screensize { get; set; }
    public string FullHD { get; set; }
    public string ThreeD { get; set; }
}

public class RootObject
{
    public string Brand { get; set; }
    public string Type { get; set; }
    public string Device { get; set; }
    public Specs Specs { get; set; }
}

This will work, but not for the purpose of what I’d like to show. We refactor the whole stuff into an object structure like this:

CodeScheme

Or, in code (put into a single file for the sake of brevity)

namespace JsonDemo
{
  public abstract class Device
  {
    public string Brand { get; set; }
    public string Type { get; set; }
  }
  
  public class Phone : Device
  {
    public PhoneSpecs Specs { get; set; }
  }
  
  public class Tv : Device
  {
    public TvSpecs Specs { get; set; }
  }
  
  public abstract class Specs
  {
    public string Screensize { get; set; }
  }
  
  public class PhoneSpecs : Specs
  {
    public string Storage { get; set; }
    public string Memory { get; set; }
  }
  
    public class TvSpecs: Specs
  {
    public string FullHd { get; set; }
    public string ThreeD { get; set; }
  }
}

If you think this is a ludicrous complicated way to store such a simple data structure I think you are quite right, but a) they don’t call me a Senior Software Architect for nothing, making things complicated is what I am told Architects do for a living, so I try to be a Good Boy ;-) and b) this is just for the purpose of the sample, so bear with me, right?

If you remember the crux of part 1: it all came down to one line of code, namely:

JsonConvert.DeserializeObject<List<Phone>>(r.EventArgs.Result);

This method actually has a second parameter: params Newtonsoft.Json.JsonConverter[] converters, which allows you to provide your own custom converters. Making those is pretty easy, and it becomes even more easy when you use the JsonCreationConverter<T> class that’s floating around the internet in various permutations. I nicked it from StackOverflow here.

using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace JsonDemo
{
  public abstract class JsonCreationConverter<T> : JsonConverter
  {
    protected abstract T Create(Type objectType, JObject jsonObject);

    public override bool CanConvert(Type objectType)
    {
      return typeof(T).IsAssignableFrom(objectType);
    }

    public override object ReadJson(JsonReader reader, Type objectType, 
      object existingValue, JsonSerializer serializer)
    {
      var jsonObject = JObject.Load(reader);
      var target = Create(objectType, jsonObject);
      serializer.Populate(jsonObject.CreateReader(), target);
      return target;
    }

    public override void WriteJson(JsonWriter writer, object value, 
   JsonSerializer serializer)
    {
      throw new NotImplementedException();
    }
  }
}

To make a converter, you subclass this object into a templated converter for the base class, override the “Create” method and off you go. Writing a converter for the Device/Phone/Tv hierarchy is pretty easy: you just have to check the value of the “Device” property, which you do like this:

using System;
using Newtonsoft.Json.Linq;

namespace JsonDemo
{
  public class JsonDeviceConverter : JsonCreationConverter<Device>
  {
    protected override Device Create(Type objectType, JObject jsonObject)
    {
      var typeName = jsonObject["Device"].ToString();
      switch(typeName)
      {
        case "TV":
          return new Tv();
        case "Phone":
          return new Phone();
        default: return null;
      }
    }
  }
}

For the Specs/PhoneSpecs/TvSpecs you do more or less the same, only now you have to check for the existence of certain properties, not the value. I decided that if an object has a “Storage” property it’s a PhoneSpecs, and if it has “FullHD” it’s a TVSpecs.

using System;
using Newtonsoft.Json.Linq;

namespace JsonDemo
{
  public class JsonSpecsConverter : JsonCreationConverter<Specs>
  {
    protected override Specs Create(Type objectType, JObject jsonObject)
    {
      if(jsonObject["Storage"] != null)
      {
        return new PhoneSpecs();
      }

      if (jsonObject["FullHD"] != null)
      {
        return new TvSpecs();
      }

      return null;
    }
  }
}

Finally, to get these converters being used by the deserializer you have to slightly modify the deserialization line:

var deserialized = JsonConvert.DeserializeObject<List<Device>>(r.EventArgs.Result, 
  new JsonDeviceConverter(), new JsonSpecsConverter());

And sure enough, if you put a breakpoint behind this line, you can place a watch on “deserialized” and see that the data structure has been deserialized in our artfully crafted class structure.

Deserialized

And that’s all there is to it. Demo solution with full code can be found here.

The third and final part of this series shows how to cache results and can be found here

01 February 2012

Behavior to force TextBox model update to prevent trouble with the ApplicationBar

A small quicky this time:

Problem:

  • TextBox, Text property bound to a string in my ViewModel
  • I type text in the TextBox
  • I click a “Save” button on my ApplicationBar
  • The string in my ViewModel is not updated. It never gets updated. WTF???

It appears the TextBox only updates it’s value to a bound string when it loses focus. And a TextBox does not lose focus when you click an ApplicationBar Button. Meh.

I have found a few solutions and workarounds, and in the end rolled my own:  a very small behavior that updates the binding every time you type something in your textbox. That’s a bit wasteful, but it works for me. It builds on the SafeBehavior pattern I wrote about earlier, and it’s so small I post it in one go:

using System.Windows.Controls;

namespace Wp7nl.Behaviors
{
  /// <summary>
  /// A behavior to for text box model update when text changes
  /// </summary>
  public class TextBoxChangeModelUpdateBehavior : SafeBehavior<TextBox>
  {
    protected override void OnSetup()
    {
      AssociatedObject.TextChanged += AssociatedObjectTextChanged;
    }

    protected override void OnCleanup()
    {
      AssociatedObject.TextChanged -= AssociatedObjectTextChanged;
    }

    void AssociatedObjectTextChanged(object sender, TextChangedEventArgs e)
    {
      var binding = AssociatedObject.GetBindingExpression(TextBox.TextProperty);
      if (binding != null)
      {
        binding.UpdateSource();
      }
    }
  }
}

I have read amongst other things Prism has a UpdateTextBindingOnPropertyChanged behavior. Well this one will be in the next version of my #wp7nl library on codeplex