SDDN Meeting, 30 June, Melbourne

June 26, 2009

EDIT: We’ll be giving away not one but two Expression Studio Suites worth over $1K each!

Come along and see Sketchflow and Blend 3 in all their glory!

Sketchflow Shane Morris, Microsoft

Don’t know what Sketchflow is? Then read this!. Okay, now tell me you dont want Shane, MS UX Evangelist, to run through it live!

Expression Blend 3 – What’s new? – Mahesh Krishnan, Readify

Expression Blend 3 improves upon the goodness of Blend 2 SP 1 by providing a whole heap of new features and more importantly, the ability to create applications for Silverlight 3. The list of new enhancements is long – Lots of improvements to the way you use the tool, Improvements to how XAML, C# and VB.NET files are edited, Support for importing Adobe Photoshop and Illustrator files, Skinning enhancements, Enhancements for animation, Sample data generation, etc, etc.

Mahesh Krishnan will run through these changes in a fast demo based session (without using Powerpoint!) The session is targeted at both Designers and Developers, so don’t miss out :)

About the speaker: Mahesh Krishnan, works as Senior Consultant at Readify and blogs at http://blogesh.wordpress.com. He has previously presented at a number of user group meetings, codecamps and Tech.Ed

We meet @ the Microsoft Theatre, Level 5, 4 Freshwater Place, Southbank. Be there from 6!

Use the registration tool on the SDDN site.


Nerd Dinner, Melbourne 9 April

April 6, 2009

This Thursday, 9th April we are having a nerd dinner in Melbourne at the Elephant and Wheelbarrow on Bourke Street – 6PM till late.

I was talking with a few old friends about catching up, and it grew from there in to an open invite to all nerds :)

Remember that Friday is a public holiday so there are no excuses!

To register (so we can book) head over to NerdDinner.com.

See you there!


The SDDN brings you “Silverlight in a day!”

January 27, 2009

Announcing “Silverlight in a day” – a full day of hands on Silverlight training brought to you by the SDDN – FREE!

When: Saturday 21st February 2009
Cost: NOTHING! (lunch is provided)
Where: Level 2, Cliftons, 440 Collins St, Melbourne
Contact: info@sddn.org.au to reserve your spot!

The SDDN has been a little quiet since its first meeting in December – but there is a great reason! Mahesh, Phil and myself have been busy organising this fantastic event.

The SDDN invites you to come along and get your hands dirty with Silverlight 2! Learn how to build Silverlight Applications using Visual Studio and Expression Studio.

In this instructor led one day course the 40 attendees will be able to work their way through hands-on labs and gain invaluable insight into the technology and how they can use it to create Rich Internet Applications (RIA).

Gain an understanding of varied Silverlight topics such as XAML, animation, data binding, communication and more and get the start you need to create great Silverlight applications!

Get in fast as spaces are limited!

Edit: The level of the training day is aimed at people who are new to Silverlight. The course is targeted at both designers and developers!


Create a Snapshot of your data in Silverlight

September 24, 2008

I’ve been working on some Silverlight projects with a designer and in a word – it’s been fantastic. Alex, my brother, and I have been learning Silverlight 2 together. It’s been a great way to figure out what works best in our little Silverlight
team.

Silverlight separates concerns between me, the developer and the designer very well. I love being able to throw a design issue over to Alex to fix. He does a “get latest”, runs it up and fixes the issue/makes the app look _not_ crap.

This is all good, until the application gets a little more complex. I add WCF services, databases and other technical dependencies which require some level of set up. Alex is quite technical, but some of these things sit outside the scope of his professional experience. This leads to a problem where we sit on the phone for an hour trying to figure out why it’s not working. “Works on my machine” seal doesn’t apply here unfortunately.

So what do you do?

There are a range of ways to fix a problem like this. One way is to use dummy test data. Put the application in to “dummy” mode and load the data from another source rather than your WCF service etc.

This means that your designers can press F5 and have the application “just work” – a pretty ideal situation you have to admit. This solution is also great for sales demonstrations – keeping a sales person’s notebook up to date with the latest website version, WCF, database etc is a PITA :) I don’t know how many times I’ve been caught before a big demo fixing the demo notebook because it has some arcane issue that never seems to occur on any other notebook I’ve ever used.

The problem then becomes – how to you get _good_ dummy data? You really don’t want to be creating this by hand… Why not set your model classes up in a way that you can take a snapshot of them and re-load it in dummy mode?

This is actually pretty easy to achieve by using the DataContractSerializer class which is built in to Silverlight.

The process overview is:

  • Design model classes in a way that supports DataContractSerialization
  • Apply DataContract attributes to the classes
  • Serialise the object graph to ISO storage
  • Find the file on the hard drive and copy in to Silverlight project
  • Add a setting to place the project in to “dummy” mode
  • Load the serialised object from the XAP (it will be compiled in)
  • Enjoy a problem free relationship with your designer :)

<Sample Code>

Serialise your Silverlight Object Graph Example

</Sample Code>

Preparing for Serialisation

There are a couple of simple rules when performing serialisation in Silverlight using DataContractSerializer.

  • In partial trust (which Silverlight runs in) you can only serialise public fields
  • It’s easiest to serialise object graphs which do not have circular dependencies

With these two rules in mind let’s smash together some code.

  • Create a new Silverlight project
  • Create some simple demonstration model classes
  • Create Serialize and Deserialize methods
  • Manually populate with test data (normally this would be some real database data)
  • Serialize data, get file, copy to project and set up for deserialization

When creating a serializable data model ensure you have one starting point. That is a main object which is the root of the object graph. Ensure that you have no circular dependencies.

  • Create two simple classes called ModelMainClass and SomeOtherClass
  • Add a couple of simple properties to ModelMainClass
  • Add a couple of simple properties to SomeOtherClass
  • Add a reference to System.Runtime.Serialization
  • Decorate each class with [DataContract] attribute
  • Decorate the properties and member variables in each class you want to serialise with the [DataMember] attribute
  • Add a List property to ModelMainClass to hold references to instances of SomeOtherClass. Ensure it is also marked with the DataMemberAttribute

[DataContract]
public class ModelMainClass
{
	[DataMember]
	public string SomeProperty
	{
		get;
		set;
	}

	[DataMember]
	public long SomeValue
	{
		get;
		set;
	}
	[DataMember]
	public List<SomeOtherClass> SomeOtherClassInstances
	{
		get;
		set;
	}
}

[DataContract]
public class SomeOtherClass
{
	[DataMember]
	public string SomeOtherClassValue
	{
		get;
		set;
	}
}

Get the data in to isolated storage

Next up we need to create the serialisation and deserialisation class.

Create a new file called Persistence.cs

This file will have the following functionality

  • A method to serialise to a byte array
  • A method to deserialise from a byte array
  • A method to write a byte array to isolated storage
  • For posterity a method to read a byte array from isolated storage
  • A method to read a byte array from the XAP file
const string PERSISTFILENAME = "persist.dat";

static List<Type> knownTypes = null;

public static void ISOSave(ModelMainClass mmc)
{
	try
	{
		MemoryStream ms = new MemoryStream();

		DataContractSerializer ser = new DataContractSerializer(mmc.GetType(), getKnownTypes());

		ser.WriteObject(ms, mmc);

		byte[] data = ms.ToArray();
		commit(data);
	}
	catch (Exception ex)
	{
		Console.WriteLine("Argh");
	}
}

static void commit(byte[] data)
{
	using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
	{
		IsolatedStorageFileStream isfs = new IsolatedStorageFileStream(PERSISTFILENAME, FileMode.Create, isf);

		isfs.Write(data, 0, data.Length);

		isfs.Close();
	}
}

static byte[] load(bool dummyData)
{
	if (dummyData)
	{
		StreamResourceInfo s = Application.GetResourceStream(new Uri("MockData/persisted.dat", UriKind.Relative));

		byte[] result = new byte[s.Stream.Length];
		s.Stream.Read(result, 0, result.Length);
		s.Stream.Close();
		return result;
	}
	else
	{
		using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
		{
			if (isf.FileExists(PERSISTFILENAME))
			{
				IsolatedStorageFileStream isfs = new IsolatedStorageFileStream(PERSISTFILENAME, FileMode.Open, isf);

				byte[] result = new byte[isfs.Length];
				isfs.Read(result, 0, Convert.ToInt32(isfs.Length));
				isfs.Close();
				return result;
			}
			else
			{
				return null;
			}
		}
	}
}

public static ModelMainClass ISOLoad(bool dummyData)
{
	byte[] data = load(dummyData);

	if (data == null)
	{
		return new ModelMainClass();
	}
	else
	{
		DataContractSerializer ser = new DataContractSerializer(typeof(ModelMainClass), getKnownTypes());
		MemoryStream ms = new MemoryStream(data);

		ModelMainClass mmc = ser.ReadObject(ms) as ModelMainClass;
		return mmc;
	}

}

private static List<Type> getKnownTypes()
{
	if (knownTypes == null)
	{
		knownTypes = new List<Type>();
		knownTypes.Add(typeof(SomeOtherClass));
		knownTypes.Add(typeof(ModelMainClass));
	}
	return knownTypes;

}

Note here the Load method has the ability to load data from isolated storage and from the dummy data in the XAP. This is for posterity and completeness :)

Generate some test data

In Page.xaml create a button to create and save the test data. In the button’s Click even drop in the following code:


ModelMainClass mmc = new ModelMainClass();

mmc.SomeProperty = string.Format("This is a test {0}", DateTime.Now.ToString());
mmc.SomeValue = DateTime.Now.Ticks;

List<SomeOtherClass> list = new List<SomeOtherClass>();

for (int i = 0; i < 100; i++)
{
	list.Add(new SomeOtherClass() { SomeOtherClassValue = i.ToString() });
}

mmc.SomeOtherClassInstances = list;

Persistence.ISOSave(mmc);

Pretend this code is getting some stuff from your WCF service etc. Serialise your completed object graph here.

Note the call to Persistence.ISOSave which is our new method…

Find the data in isolated storage

Silverlight keeps its isolated storage underneath the user’s data folder.

On Vista look under here: C:\Users\<user>\AppData\LocalLow\Microsoft\Silverlight\is
On XP look under here: C:\Documents and Settings\<user>\Local Settings\Application Data\Microsoft\Silverlight\is

You will need to have a bit of a hunt around in these folders to find what you are looking for (search doesn’t seem to work). For example on my machine the file was located here:

C:\Users\jordank\AppData\LocalLow\Microsoft\Silverlight\is\tuigc5pi.rqh\xhfonuik.kdv\1\s\rqotqem0g1s0rro4dxwbnvcvci50t01b4knyscivinuy3ejenraaaeda\f.

Nice.

Copy this file in to your Silverlight project, and set it’s Build Action to “Content”. Setting this to content allows the Persistence class to read the data using the following code:

StreamResourceInfo s = Application.GetResourceStream(new Uri("MockData/persisted.dat", UriKind.Relative));

Finishing off

Back in Page.xaml, create another button to load the data, and a TextBlock to proove the load worked. In the click event for the button drop the following code:

ModelMainClass mmc = Persistence.ISOLoad(true);
foreach (SomeOtherClass soc in mmc.SomeOtherClassInstances)
{
	SomeOutput.Text += soc.SomeOtherClassValue;
}

Too easy! You just loaded your snapshot from the XAP file!

You can see how easy it would be to build complex dummy data object graphs and distribute them with your application.

And everyone lives happily ever after