Binary Serialisation In Silverlight

One problem with the Silverlight DataContractSerializer is that it does not maintain reference links to objects. For example: if you had a customer object "Mr Green" and 2 order objects "Cooker" & "Fire" that both held references to the (single) "Mr Green", when serialised and then deserialised using DataContractSerializer the "Cooker" would point to a different "Mr Green" than the "Fire", i.e. they are not reference equal. If this is an undesirable scenario we can choose to serialise in a binary, reference-equal way so that when we deserialise there will still only be 'one' "Mr Green".

One option is to make use of a 3rd party library such as CSLA Light. You can use CSLA Light just to enable binary serialization or you could embrace the whole CSLA architecture. Either way you will probably need to change the inheritance structure of your objects and replace any properties with CSLA properties. You can find out more about CSLA Light at http://www.lhotka.net/weblog/UsingCSLALightPart1.aspx

Example of simple CSLA

 For our Customer objects to be CSLA binary serializable we would modify the class to look something like:

    [Serializable]
    public class Customer : BusinessBase<Customer>
    {

        private static PropertyInfo<string> CustomerNameProperty = RegisterProperty<string>(new PropertyInfo<string>("CustomerName", "CustomerName", string.Empty));

        public string
CustomerName
        {
            get
            {
                return GetProperty(CustomerNameProperty);   
            }
            set
            {
                
             SetProperty(CustomerNameProperty, value);   
            }
        }

We would follow a similar pattern for out order class. We could then use CSLA's MobileFormatter to serialise/deserialise (the example below defines generic methods but non-generic/typed methods could also be used):

        public static T Load<T>(Stream stream)
        {
            T m = default(T);

            Csla.Serialization.Mobile.MobileFormatter f = new Csla.Serialization.Mobile.MobileFormatter();
            m = (T) f.Deserialize(stream);

            return m;
        }


        public static void Save<T>(T obj, Stream stream)
        {
            Csla.Serialization.Mobile.MobileFormatter m = new Csla.Serialization.Mobile.MobileFormatter();
            m.Serialize(stream, obj);
        }

 

There are alternatives to CSLA Light for getting binary serialisation such as http://slserializelzo.codeplex.com/ although I've not investigated them as yet. (Hopefully a future version of Silverlight will allow the DataContractSerializer to output XML (albeit 'non standard') with referential links.

SHARE:

Detecting when a Silverlight app enters full screen mode

Obviously you know when a users clicks your full screen button but a the user can press escape to exit full screen mode at any time, an alternative is to respond to the FullScreenChanged event.

For example:

     public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
            App.Current.Host.Content.FullScreenChanged += new EventHandler(FullScreenChanged);
        }

        void FullScreenChanged(object sender, EventArgs e)
        {
            if (App.Current.Host.Content.IsFullScreen)
                txtFullScreen.Text = "Running in full screen.";
            else
                txtFullScreen.Text = "Not running in full screen.";
        }


        private void btnFullScreen_Click(object sender, RoutedEventArgs e)
        {
            App.Current.Host.Content.IsFullScreen = true;
        }
    }

The above assumes a button to enable the user to select full screen and a textblock:

 

<UserControl x:Class="blog_misc_temp.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
  <Grid x:Name="LayoutRoot">
        <StackPanel>
            <TextBlock Name="txtFullScreen" Text="Not running in full screen."/>
            <Button Click="btnFullScreen_Click" Content="Enter Full Screen"></Button>
        </StackPanel>
    </Grid>
</UserControl>

 

SHARE:

Free Xaml drawing tool

I stumbled upon a nice (free) open source drawing application (a la Adobe Illustrator) which allows saving in SVG but also XAML! So if you don't want to/cannot afford to use Blend this could be a nice alternative, you can download from http://www.inkscape.org - should also mention you can get a 60-day evaluation copy of Blend 3 from Microsoft.

SHARE:

Silverlight 3 WritableBitmap pixel colour values

Rather than taking an array of Color objects, the WritableBitmap.Pixels property holds an array on ints which represent premultiplied ARGB colour values. To set a given pixel to a given colour you have to take the alpha, red, green and blue values and convert them to a premultiplied ARGB int value.

The following code contains some helpers/extension methods to make the process bit easier, for example to set every pixel to red:

for (int index = 0; index < bmp.Pixels.Length; index++)
{
   Color myColour = new Color() { A = 255, R = 255, G = 0, B = 0 };
   bmp.Pixels[index] = myColour.ToWritableBitmapPixelValue();
}

 or using the Fill extension method:

bmp.Fill( new Color() { A = 255, R = 255, G = 0, B = 0 } );

WritableBitmapHelper class listing

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Media.Imaging;

namespace BitmapAPI
{
    /// <summary>
    /// Helper methods\extension methods for dealing with WritableBitmap,
    /// in real world implementation you'd probably choose to separate the
    /// extension methods iinto separate static classes;
    /// eg WritableBitmapExtensions & ColorExtensions
    /// </summary>
    public static class WritableBitmapHelper
    {
        /// <summary>
        /// Converts ARGB byte values to an integer
        /// Based on info found at:
        /// http://blogs.silverarcade.com/silverlight-games-101/15/silverlight-writeablebitmap-pixel-format-in-silverlight-3/
        /// </summary>
        /// <param name="alpha">Alpha transparency: 0=transparent  255=solid</param>
        /// <param name="red">Amount of red: 0 to 255</param>
        /// <param name="green">Amount of green: 0 to 255</param>
        /// <param name="blue">Amount of blue: 0 to 255</param>
        /// <returns>An integer representing an ARGB color</returns>
        public static int CalcWritableBitmapPixelValue(byte alpha, byte red, byte green, byte blue)
        {
            // Calc premultiplier once only. We need to use premultiplied ARGB32
            // rather than convential ARGB.
            double alphaPreMultiplier = alpha / 255d;

            // Premultiply rgb values with alpha
            byte r = (byte)(red   * alphaPreMultiplier);
            byte g = (byte)(green * alphaPreMultiplier);
            byte b = (byte)(blue  * alphaPreMultiplier);

            return (alpha << 24) | (r << 16) | (g << 8) | b;
        }



        /// <summary>
        /// Extension method to convert a System.Windows.Media.Color to an integer value.
        /// </summary>
        /// <param name="color">The System.Windows.Media.Color to convert</param>
        /// <returns>An integer representing the ARGB values of <paramref name="color"/></returns>
        public static int ToWritableBitmapPixelValue(this Color color)
        {
            return CalcWritableBitmapPixelValue(color.A, color.R, color.G, color.B);
        }



        /// <summary>
        /// Extension method to 'fill' a WriteableBitmap with a given solid color
        /// </summary>
        /// <param name="bmp">The WriteableBitmap to fill</param>
        /// <param name="color">The Color to fill with</param>
        public static void Fill(this WriteableBitmap bmp, Color color)
        {
            for (int i = 0; i < bmp.Pixels.Length; i++)
            {
                bmp.Pixels[i] = color.ToWritableBitmapPixelValue();
            }
        }

    }
}

 

 

 

SHARE:

Understanding Lambda Expressions

Of all the additions to the C# language, lambda expressions are potentially the most confusing. Part of this might be due to the odd look of the syntax when you first see it or that a lot of the examples use single letters in the expressions.

The best way to start thinking about lambdas is to think of them simply as anonymous methods.

Suppose we have declared a Timer in a WinForms application as: Timer t = new Timer(); We now need to wire up the Timer's Tick event to some code that is to be executed when the Timer fires.

There are various ways to do this without using lambdas:

  1. Declare an explicit event handler method

    void t_Tick(object sender, EventArgs e)
    {
        textBox1.Text = DateTime.Now.ToString();
    }

    ...
    t.Tick +=new EventHandler(t_Tick); or using delegate inference t.Tick += t_Tick;

  2. Use an anonymous method

    t.Tick += delegate(object sender2, EventArgs e2)
    {
       textBox1.Text = DateTime.Now.ToString();
    };


To write the above using a lambda expression you could write:

t.Tick += (object sender2, EventArgs e2) => textBox1.Text = DateTime.Now.ToString();

Or using type inference:

t.Tick += (sender2, e2) => textBox1.Text = DateTime.Now.ToString(); 

These are examples of expression lambdas. Another type is the statement lambda which is similar but can contain multiple statements enclosed in braces; for example we could write the following:

t.Tick += (object sender2, EventArgs e2) =>
{
    textBox1.Text = DateTime.Now.Minute.ToString();
    textBox2.Text = DateTime.Now.Second.ToString();
};

Note: the => is typically read as "goes to".

Another Example

To print all numbers in a list of ints to a TextBox:

List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
numbers.ForEach(number => textBox1.Text += number.ToString());

To print all number from 6 and up:

List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
numbers.ForEach(number =>
{
    if (number > 5)
        textBox1.Text += number;
});

or:

List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
numbers.FindAll(number => number > 5).ForEach(number => textBox1.Text += number.ToString());

If you want to fill in the gaps in your C# knowledge be sure to check out my C# Tips and Traps training course from Pluralsight – get started with a free trial.

SHARE: