Browse by Tags

All Tags » silverlight 4   (RSS)

One feature I employ often in Silverlight projects is the ability to share a model between the client and the server. When you expose a model using a WCF service, you can consume it on the Silverlight side and indicate you want to reuse types in a referenced assembly, rather than having the proxy types generated. At first glance this seems ideal because you can truly project behavior such as validation to the client without maintaining separate copies of the type in question. Upon further inspection, however, there can be some unexpected side effects.

Consider the following class that is defined in a standalone Silverlight assembly but shared on the server by adding it as a linked file:

[DataContract]
public class SimpleModel
{
    public SimpleModel()
    {
        NonMemberProperty = "This was initialized within the constructor.";
    }

    private string _field = "This is an initialized field.";

    public string NonMemberProperty { get; set; }
        
    [DataMember]
    public string MemberProperty { get; set; }
        
    public string Field
    {
        get { return _field; }
    }
}

I've purposefully packed a few different examples to help illustrate what is happening. It should be very clear what will happen when you instantiate the class. The field will be initialized to expose a value, the non-member will be given a value, and the member property (the one tagged as a data member) is initialized to the default value of null.

Now you can expose the model using a web service. Just add a new "Silverlight-enabled Web Service" to your web project, and give it a very simple operation to fetch a new instance of the model:

[ServiceContract(Namespace = "http://jeremylikness.com/examples/")]
[SilverlightFaultBehavior]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class SimpleService
{
    [OperationContract]
    public SimpleModel GetSimpleModel()
    {
        var simpleModel = new SimpleModel
                                {
                                    MemberProperty = "This was initialized by the service."
                                };
        return simpleModel;
    }
}

What happens now? On the server, you'll get a new object that now has three fully populated properties - the field (which returns the value initialized on the internal field), the non-member property, and the member property. So far, so good.

Flip over to the Silverlight client side. Create a grid that has rows and columns for the labels and the values. Embed an instance of the model like this:

<Grid.DataContext>
    <Model:SimpleModel/>
</Grid.DataContext>

And then you can easily data-bind the values like this:

<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Field}" 
            Style="{StaticResource ValueStyle}"/>
<TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding NonMemberProperty}" 
            Style="{StaticResource ValueStyle}"/>
<TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding MemberProperty}" 
            Style="{StaticResource ValueStyle}"/>

Add a button for the user to click. We'll forget MVVM for now (heck, our model didn't even implement property change notification) and just implement a code behind. Right now the model should create an instance in the designer and show you the two initialized fields — something like this:

If you do nothing in the code-behind you should still be able to run the application and see the initialized values. Now let's get down to the wire.

Add a service reference, only make sure you specify that it re-uses types. You get to the dialog by clicking on the "advanced" button when adding a new service. It should look something like this:

This ensures that the service will return the actual type represented by the model, rather than generating a proxy type that lives in the namespace of the service itself. You get to have the full type with all of the methods and functions you've defined, even if they aren't being sent over the wire. Now that's handy, right?

In the code behind for the button click, simply fetch the instance generated on the server and update the data context:

private void Button_Click(object sender, RoutedEventArgs e)
{
    ((Button) sender).IsEnabled = false;
    var client = new ServiceReference.SimpleServiceClient();
    client.GetSimpleModelCompleted += _ClientGetSimpleModelCompleted;
    client.GetSimpleModelAsync();
}

void _ClientGetSimpleModelCompleted(object sender, ServiceReference.GetSimpleModelCompletedEventArgs e)
{
    btnLoad.IsEnabled = true;
    LayoutRoot.DataContext = e.Result;            
}

Not too complicated, right?

If you run the application and click the load button, the code-behind will call the service and fetch a new instance. When the instance is bound to the data context, however, you may notice something strange. The property that was flagged as a data member and was set on the server comes through just fine, but the other properties are empty. How can that be? Even though you didn't tag them as data members, they should have been set when the type was constructed. The field property doesn't even have a setter.

This is as expected, but what about the other two properties? The answer is well-documented but often overlooked. If you read the documentation for the data contract serializer, or the XML object serializer that it is based on, you'll find a small but important sentence that explains: "When instantiating the target object during deserialization, the DataContractSerializer does not call the constructor of the target object." That explains the non-member property. When the serializers create the type, they by pass the normal type system. This makes sense because you are expecting to reconstruct the type based on the contract, so the properties not passed in the contract aren't really relevant. The type is built from the ground-up by setting the properties that were serialized, but no other initialization code is called.

If you're wondering about the field, it's the same problem. While the C# language allows you to initialize fields as a convenience, the code is actually moved into the constructor for the type. If you decompile the DLL for the model used in this example, this is what the decompiled constructor will look like:

public SimpleModel()
{
 this._field = "This is an initialized field.";
 base();
 this.NonMemberProperty = "This was initialized within the constructor.";
}

As you can see, the compiler conveniently moved the field initialization into the constructor. All of the initialized fields will be called from the start of the constructor before calling into the base object constructor and then handling the code you specify.

So what's the point? It is very important that you understand the implications of sharing types between the server and the client, especially when there are behaviors you are expecting. If you have certain properties that are initialized in the constructor, you can't expect them to be available when addressing the instances on the client. One way to deal with this is to move initialization logic into a separate method and call it from the constructor but expose it so you can call it elsewhere as well. This may work in some cases but often the reason for putting code into the constructor is to hide the implementation details of how the type is initialized from the consumer. If that's the case, it's probably better to make sure all of your exposed properties and methods handle initialization appropriately without a dependency on the constructor. For example, remove the initialization code for the field and replace the property code with this:

get { return _field ?? (_field = "This was initialized in the getter."); }

Now the field will be initialized on first access and never initialized again, but it will work equally well regardless of how it is instantiated. Another way to keep the initialization details private is to track the initialization state with a private field. Booleans default to false so the field will have that value whether the type was created with a call to its constructor or not. Your code can check the value of this field and call the initialization logic the first time it is needed.

Sharing types between the client and the server is a powerful feature that Silverlight provides. It is important that you understand the nuances of how it works so that you can construct your classes to behave consistently and don't fall victim to unexpected behaviors on the client because the constructors were never called for your types.

Download the sample solution here.

Jeremy Likness

The biggest problem with data-binding is the requirement to implement the INotifyPropertyChange interface. There are dozens of solutions out there that try to simplify the process with techniques ranging from parsing lambda expressions and walking the stack frame to using IL weaving to modify classes at compile time. The most popular approach is to derive from a base class and call a base method to handle the event.

The frustration often comes from mapping data objects that don't implement the interface to view models that do. Wouldn't it be nice to have a simple, straightforward way to manage this without duplicating properties and writing tedious mapping code? It turns out there is.

For this particular problem, I started with the solution. Given a model, say, a ContactModel, I wanted to be able to do this:

public PropertyNotifier<ContactModel> Contact { get; set; } 
public void SetContact(ContactModel contact) 
{
   Contact = new PropertyNotifier(contact); 
}

In other words, a nice type would wrap the object and expose it with full property change glory, and little effort on my part.

So, where to start? To begin with I created a simple base class that allows for property change notification. For now I'm going to ignore some of the interesting ways to actually call the notification.

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

    public void RaisePropertyChange(string propertyName)
    {
        var handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

This class is really all you need to have your own MVVM framework. Next is some heavy lifting. Because the solution uses dynamic types and heavy reflection, it will not work on Windows Phone 7. It will, however, work with Silverlight 4, and there is perhaps an even more elegant solution to be derived from this work in Silverlight 5 by adding ICustomTypeProvider to the mix.

How can this create a bindable object in Silverlight 4 or 5? First, create the shell of the view model. It should create the proxy class with property change notification. It should allow you to pass in a template and have that template mirrored by the proxy. Ideally, it should be easy to get the template back out (i.e. yank out the original model to send on its way after it has been modified). Here's the start:

public class PropertyNotifier<TTemplate> : BaseNotify where TTemplate : class
{
   public TTemplate Instance { get; set; }
   public INotifyPropertyChanged NotifyInstance { get; set; }
}    

Simple enough. Not sure if the notifier instance really deserves a public setter... but it is there for now. Now comes the fun part!

The type must be created on the fly, so it needs a dynamic assembly and module to host the type. There is no sense in creating a new one for each type, so these can be static properties that live on the notifier. There should also be a type dictionary to map the source type to the proxy type (to avoid recreating the proxy type) and a mutex to avoid collisions with the dictionary (thread safety).

private static readonly ModuleBuilder _builder;
private static readonly Dictionary<Type, Type> _types = new Dictionary<Type, Type>();
private static readonly object _mutex = new object();        

static PropertyNotifier()
{
    var assemblyName = new AssemblyName("PropertyNotifier");
    var currentDomain = AppDomain.CurrentDomain;
    var builder = currentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);

    _builder = builder.DefineDynamicModule("PropertyChangeModels");
}

If you are afraid of collisions you can give the assembly a creative name like a GUID or append random text and strings if you like. This makes it nice and readable in the debugger. The assembly is created in the current domain and the module defined to host dynamic types.

Without understanding the details of how the type is actually built, you can still wire in the constructor and put in a placeholder, like this:

public PropertyNotifier()
{
    Monitor.Enter(_mutex);
    try
    {
        if (!_types.ContainsKey(typeof (TTemplate)))
        {
            _types.Add(typeof(TTemplate), _BuildType()); 
        }                                
    }
    finally
    {
        Monitor.Exit(_mutex);
    }

    var type = _types[typeof (TTemplate)];
            
    NotifyInstance = (INotifyPropertyChanged)Activator.CreateInstance(type);                    
}

public PropertyNotifier(TTemplate instance) : this()
{
    Instance = instance;
}

If the type has not been created, it is built. An overloaded constructor will take in an instance and then set it.

Next, assuming the type is built (we'll get into the gory details later), a few methods will help with mapping properties. First, define a delegate for the getter and setter. Then, define a dictionary of dictionaries. The key to the outer dictionary will be the type, and the inner dictionary will map the property name to the getter or setter method.

private delegate void Setter(object target, object value);

private delegate object Getter(object target);

private static readonly Dictionary<Type, Dictionary<string,Setter>> _setterCache = new Dictionary<Type, Dictionary<string,Setter>>();
private static readonly Dictionary<Type, Dictionary<string,Getter>> _getterCache = new Dictionary<Type, Dictionary<string, Getter>>();

The helper methods will inspect the type for the property information and use reflection to grab the getter or setter. They will then store these in the cache for future look ups:

private static object _GetValue(object target, string property)
{
    Monitor.Enter(_mutex);
    try
    {
        if (!_getterCache[target.GetType()].ContainsKey(property))
        {
            var method = target.GetType().GetProperty(property).GetGetMethod();
            _getterCache[target.GetType()].Add(property, obj => method.Invoke(obj, new object[] {}));
        }
    }
    finally
    {
        Monitor.Exit(_mutex);
    }

    return _getterCache[target.GetType()][property](target);                
}

private static void _SetValue(object target, string property, object value)
{
    Monitor.Enter(_mutex);
    try
    {
        if (!_setterCache[target.GetType()].ContainsKey(property))
        {
            var method = target.GetType().GetProperty(property).GetSetMethod();
            _setterCache[target.GetType()].Add(property, (obj,val) => method.Invoke(obj, new[] { val }));
        }
    }
    finally
    {
        Monitor.Exit(_mutex);
    }

    _setterCache[target.GetType()][property](target, value);
}

You can call the first with an object and the property name to get the value. Call the second with the object, the property name, and the property value to set it. Subsequent calls will not require inspection of the properties as the methods will be cached to call directly (and if you really want to speed it up, look into dynamic methods).

So the proxy still hasn't been built yet, but that's more complicated. First, get the simple stuff out of the way. When the instance is passed in, automatically wire the properties to the proxy. When the proxy is created, hook into the property change notificaton to automatically push changes back to the original instance:

private TTemplate _instance;

// original object
public TTemplate Instance
{
    get { return _instance; }
    set
    {                
        _instance = value;
        NotifyInstance = (INotifyPropertyChanged)Activator.CreateInstance(_types[typeof (TTemplate)]);

        foreach(var p in typeof(TTemplate).GetProperties())
        {
            var sourceValue = _GetValue(value, p.Name);
            _SetValue(NotifyInstance, p.Name, sourceValue);
        }

        RaisePropertyChange("Instance");
    }
}

// proxy object
private INotifyPropertyChanged _notifyInstance;

public INotifyPropertyChanged NotifyInstance
{
    get { return _notifyInstance; }
    set
    {
        if (_notifyInstance != null)
        {
            _notifyInstance.PropertyChanged -= _NotifyInstancePropertyChanged;
        }

        _notifyInstance = value;
        _notifyInstance.PropertyChanged += _NotifyInstancePropertyChanged;

        RaisePropertyChange("NotifyInstance");                
    }
}

void _NotifyInstancePropertyChanged(object sender, PropertyChangedEventArgs e)
{
    if (Instance == null)
    {
        return;
    }           

    if (_setterCache[typeof (TTemplate)].ContainsKey(e.PropertyName))
    {
        _SetValue(Instance, e.PropertyName, _GetValue(NotifyInstance, e.PropertyName));
    }
}

OK, all of the proxy and marshalling is in place. Now it's time to build the type! First step is to define the type name and set the parent so it derives from the BaseNotify object:

private static Type _BuildType()
{
    var typeBuilder =
        _builder.DefineType(string.Format("{0}Notifier", typeof (TTemplate).Name), TypeAttributes.Class | TypeAttributes.Public);

    typeBuilder.SetParent(typeof(BaseNotify));
}

Next, grab a handle to the property change method from the base class and set up a dictionary to cache the getters and setters on the template type:

var propertyChange = typeof(BaseNotify).GetMethod("RaisePropertyChange", new[] { typeof(string)});

_getterCache.Add(typeof(TTemplate), new Dictionary<string, Getter>());
_setterCache.Add(typeof(TTemplate), new Dictionary<string, Setter>());
                        

Now comes the fun part, looping through the properties and caching the getters/setters (this is from the template):

foreach(var p in typeof(TTemplate).GetProperties())
            {
                var getterInfo = p.GetGetMethod();
                _getterCache[typeof(TTemplate)].Add(p.Name, obj=>getterInfo.Invoke(obj, new object[]{}));

                var setterInfo = p.GetSetMethod();
                _setterCache[typeof(TTemplate)].Add(p.Name, (obj,value)=>setterInfo.Invoke(obj, new[]{value}));
}

Each property has a private backing field, so create the field on the proxy type:

var field = typeBuilder.DefineField(string.Format("_{0}", p.Name), p.PropertyType, FieldAttributes.Private);                

Next, define the property.

var property = typeBuilder.DefineProperty(p.Name, PropertyAttributes.HasDefault, p.PropertyType,null);

The property needs a getter. This is where the code is a little more interesting becaues it requires emitting IL code. Fortunately, you can build a sample class and use ILDASM.EXE to disassemble it and learn what the proper op codes are. Here is the getter method:

var getter = typeBuilder.DefineMethod(string.Format("get_{0}", p.Name),
    MethodAttributes.Public |
    MethodAttributes.SpecialName | 
    MethodAttributes.HideBySig,
    p.PropertyType, Type.EmptyTypes);
var getterCode = getter.GetILGenerator();

getterCode.Emit(OpCodes.Ldarg_0);
getterCode.Emit(OpCodes.Ldfld, field);
getterCode.Emit(OpCodes.Ret);

Next is the setter method. The setter method has some extra code that loads the property name and then calls the property change method. That is why the handle to the method was captured earlier.

var setter = typeBuilder.DefineMethod(string.Format("set_{0}", p.Name),  
    MethodAttributes.Public |
    MethodAttributes.SpecialName |
    MethodAttributes.HideBySig, null,
    new[] { p.PropertyType });

var setterCode = setter.GetILGenerator();

setterCode.Emit(OpCodes.Ldarg_0);
setterCode.Emit(OpCodes.Ldarg_1);
setterCode.Emit(OpCodes.Stfld, field);


// property change
// put the property name on the stack
setterCode.Emit(OpCodes.Nop);
setterCode.Emit(OpCodes.Ldarg_0);
setterCode.Emit(OpCodes.Ldstr, p.Name);
setterCode.Emit(OpCodes.Call, propertyChange);
setterCode.Emit(OpCodes.Nop);                

setterCode.Emit(OpCodes.Ret);

Now that the methods have been generated, they must be attached to the property:

property.SetGetMethod(getter);
property.SetSetMethod(setter);

That's the hard part! The easy part is to define a default constructor (calls down to the base) and create the actual type. Remember, this is the method called in the constructor so the type is returned and stored in the dictionary, then the activator is used to create the instance. Also, go ahead and set up the getter and setter cache:

typeBuilder.DefineDefaultConstructor(MethodAttributes.Public);            
            
var type = typeBuilder.CreateType();
            
_getterCache.Add(type,new Dictionary<string, Getter>());
_setterCache.Add(type,new Dictionary<string, Setter>());
            
return type;

Believe it or not, that's what it takes to build a proxy, assuming the base class contains simple properties and no complex nested types or structures. Here's a simple template to test the proxy with:

public class ContactTemplate
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }        
}

Here's a view model that is based on the template. It uses the property notifier to wrap the properties with property change notification. It also creates a default template in the constructor just to give you some information to work with when the application runs:

public class ContactViewModel : PropertyNotifier<ContactTemplate>
{       
    public ContactViewModel()
    {
        var template = new ContactTemplate
                            {
                                Id = 1,
                                FirstName = "Jeremy",
                                LastName = "Likness"
                            };
        Instance = template;
    }       
}

Now some XAML to bind it all together:

<Grid x:Name="LayoutRoot" Background="White">
    <Grid.DataContext>
        <ViewModels:ContactViewModel/>
    </Grid.DataContext>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="Auto"/>
    </Grid.ColumnDefinitions>
    <TextBlock Text="First Name: "/>
    <TextBlock Text="Last Name: " Grid.Row="1"/>
    <TextBlock Text="Edit First Name: " Grid.Row="2"/>
    <TextBlock Text="{Binding NotifyInstance.FirstName}" Grid.Column="1"/>
    <TextBlock Text="{Binding NotifyInstance.LastName}" Grid.Row="1" Grid.Column="1"/>
    <TextBox Text="{Binding NotifyInstance.FirstName,Mode=TwoWay}" Grid.Row="2" TextChanged="TextBox_TextChanged" Grid.Column="1" Width="200"/>
</Grid>

When you run the application, you'll find the property change works just fine. Now, with this helper class, anytime you need to take a simple data object and implement property change, you can just wrap it in the property notifier and bind to the InstanceNotifier property. This works perfectly well in Silverlight 4.

Of course, I won't leave you hanging. Here's the source code to play with!

Jeremy Likness

I'm please to share that I released the alpha version of the Sterling Object-Oriented Database for Silverlight 4.0 and Windows Phone 7.0 applications today.

I dug into more details about the project in this introductory post. There have not been many significant changes to the source code since then, but I did create a set up project that installs the DLLs and configures the registry keys so they appear in the "add reference" dialog on the .NET tab for both Silverlight and Windows Phone 7 applications.

Please take a moment to read and participate in the release discussion that you can find by clicking here. You can grab the installer and the source code at this link.

I'm one person with some part time help on the team and we all have full time careers so it's tough to give the project the attention and detail it deserves. I learned in the past that sometimes it's more import to "get it going" than to wait for it to "get done right." Instead of holding back months before formalizing the release, I wanted to get it out there so people can use it, comment on it, and provide feedback.

You can help our team in two very important ways. First, if you use the tool, please provide feedback, both positive and constructive, so we know where/when/how the project is being used and how to prioritize future improvements.

Second, if you are a developer and feel you can contribute your skills, please contact me and we can discuss you joining the team. Probably the two biggest needs on the team right now are someone who has the time to build out a more thorough reference application for the Windows Phone 7 version, and someone who is an installation wizard to help improve the install process. The documentation is also rudimentary so technical writers are welcome as well.

Thanks, and I look forward to your feedback!

Jeremy Likness

After posting about profiling Silverlight 4 out of the box, the author of a tool was kind enough to share with me his free .NET profiling tool. It's free, and it does a lot more than Silverlight. The manual is very straightforward but I wanted to make a quick an easy "light tour" to show you how I profiled the X-Fit app using the tool. In less than 4 minutes I'll run two different profiles, a trace and a memory scan. The memory scan lets you see individual classes, number of objects, size, etc, so the video doesn't tap into the full features, but should show how fast and easy it makes profiling.

Sorry, this was quick and dirty over lunch so I didn't encode it to Silverlight - Jing and ScreenToaster came through (link to new window):

Jeremy Likness

It turns out you can profile Silverlight 4 applications. Really! But the steps are scattered about the web in bits and pieces, so I wrote this to pull them all together. I'm going to use my reference X-Fit application for this, but you can obviously insert your own. Here we go!

Set up PowerShell

Yeah, we're going to make things a little easier and set up PowerShell. If you're not familiar with PowerShell, don't worry. Here is a decent description of PowerShell, but if you really want to get deep into it, read Wintellectual John Robbin's blog which is full of goodness. Really the main thing you want to do is to enable script support in PowerShell, and get familiar with running scripts.

Set up your Symbol Server

We're going to need a valid symbol server to make things work. If you're not familiar with this, it's basically a place that Windows debug can go to figure out symbols (labels, names, etc) for code as you are debugging, profiling, etc. John Robbins has a fantastic script that you can use to set this up.

  1. Get John Robbins' script here (just copy it and save it to a file called "symbolsetup.ps1" and if I have to tell you without the quotes, you're not ready to profile)
  2. Execute the script in PowerShell. You must specify the full path and add a flag. I do it like this: & "c:\users\jeremylikness\my documents\powershell\symbolsetup.ps1" -public
  3. This should set it all up for you. Beware! The first time you debug, you will have quite a delay as all of the symbols are downloaded - this only happens once.

Prepare your Application

To profile, you must compile the application in release mode. Yes, you read that correctly. The symbol server will provide all of the symbols and details necessary, but you must compile in release mode for this to work.

In our example, we'll pull down the Reference X-Fit Application. Download it, unzip it, and build it in release mode.

While you can debug most applications from a test page, this application uses dynamic modules so it is best to publish it to a site. You can use your local development environment, but it's easier if you just make an application in IIS. I'll leave that to you, but when we profile, the parameter we'll pass to launch it will be some type of URL.

Let's Profile!

First, credits go to the Windows Profiler Team for their detailed post for this. It contains what I'm going to share here, but I was missing some of the setup.

Go to your start menu, navigate to Visual Studio 2010, Tools, and select the command prompt as an Administrator.

Launch the Visual Studio 2010 Command Prompt

  1. Navigate to the release directory for the main XAP file. In this case, it is under XFit/Bin/Release for the main XAP in X-Fit. If you have dynamic modules, you can copy the DLL and PDB files to this directory.
  2. Open Task Manager and sort by image name. Note the PIDs of the existing iexplore.exe processes.
  3. Set up the profiling environment:
    vsperfclrenv /sampleon
  4. Launch a new process, passing the page you want to debug:
    "c:\program files (x86)\internet explorer\iexplore.exe" http://localhost/xfit/
  5. Note the new IE process (Hint: you can also go into Visual Studio and choose "attach to process" to see the title/type of process to narrow down the correct one that is hosting the Silverlight application — don't actually attach, just use this to get the process identifier)
  6. Start profiling the process (in this case, my PID was 4436):
    VSPerfCmd /start:sample /output:xfitdata /attach:4436
  7. Now go into the application and perform some actions. I created an account, then looked at my BMI, then updated my account and put in some errors and hovered over some information icons just to get a good sample
  8. End the session:
    VSPerfCmd /detach
    VSPerfCmd /shutdown
    VSPerfClrEnv /off

Examine the Data

Once I shut everything down, a new file was created called xfitdata.vsp. Now the fun part: analyzing the data. In Visual Studio 2010, you can go to File -> Open File and navigate to the VSP file to open it. You'll see a message that it is analyzing the file. This may take several minutes, so be patient. If you have your output window open, you should see messages as the symbols are analyzed:

Loading Symbols

Probably the easiest way to filter the data is to go to the module view:

Module View

Then you can expand and see where the application is spending it's time:

Expanding Profiler Info

If you double-click on the higher level item, a window will open with the details including (if available) the source code.

Sample Profiler Data

There you have it ... step-by-step profiling Silverlight 4.

Jeremy Likness

In my experience working with Silverlight applications, probably one of the most underused features I've witnessed is the ability to abstract application-level functionality using the IApplicationService and IApplicationLifetimeAware interfaces. This, in turn, results in the over-use (and abuse) of the Startup and Exit events in the Application object. Before you get angry with me shaking a finger, I'll admit I've done this quite a bit myself.

IApplicationService

The IApplicationService interface allows you to define a class that is part of the overall application lifecycle. It provides a mechanism to create a service that lasts the duration of a Silverlight application. It is called once when the application starts with an ApplicationServiceContext, and called again when the application ends.

One of the most useful things you can do with this service class is use it to intelligently parse parameters passed to the Silverlight application. How many times have you found yourself hooking into the application startup and then parsing these out? What's worse, in larger, complex applications, many different portions of the application share responsibility for handling these parameters. It breaks the concept of loose coupling to have a single front-end parsing it out and then stuffing it into an object to dole it out to the consumers that need it.

By implementing IApplicationService, you can create a service for your functionality that handles its own initialization parameters. There is no "central" place that has to understand everything. Silverlight supports using multiple application services, so you can have a logger service that looks at the logging parameter and a file upload service that looks at the file storage location parameter, so on and so forth.

Here's what a service that handles writing to the debugger might look like:

public class LoggerService : IApplicationService
{
    const string TRACE_LEVEL_KEY = "TraceLevel";
            
    public LoggerService()
    {
        _traceLevel = TraceLevel.Warning; // default
    }
   
    private TraceLevel _traceLevel; 

    public ILogger Logger { get; private set; }
        
    public static LoggerService Current { get; private set; }

    public void StartService(ApplicationServiceContext context)
    {
        Current = this;
        if (context.ApplicationInitParams.ContainsKey(TRACE_LEVEL_KEY))
        {
            _traceLevel = (TraceLevel)Enum.Parse(typeof (TraceLevel), context.ApplicationInitParams[TRACE_LEVEL_KEY], true);
        }

        Logger = new CustomLogger(TraceLevel);
        Logger.WriteLine(TraceLevel.Information, "Logger service started.");
    }

    public void StopService()
    {
        Logger.WriteLine(TraceLevel.Information, "Logger service stopped.");
    }
}

This service now allows me to configure the logging level in the web page using initParams, like this:

<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">
   <param name="source" value="ClientBin/MySilverlightApp.xap"/>
   <param name="onError" value="onSilverlightError" />
   <param name="initParams" value="TraceLevel=Warning" />
   <param name="background" value="white" />
   <param name="minRuntimeVersion" value="4.0.50401.0" />
   <param name="autoUpgrade" value="true" />    
</object>

What's more, if it is in a project by itself, adding the service to a new application is so simple it's hard to believe more people don't take advantage of this. After referencing the project, I won't have to mangle my App.xaml.cs and hook into any events in order to use the new service, parse out parameters, etc. Nope, I just add a simple reference to it in the App.xaml that looks like this:

<Application.ApplicationLifetimeObjects>
    <MySilverlightApp:LoggerService/>
</Application.ApplicationLifetimeObjects>

IApplicationLifetimeAware

Now, if you really want to do some cool things, you can extend the class even further by implementing IApplicationLifetimeAware. This will give you four additional methods: Starting, Started, Exiting, and Exiting.

Use these to perform set up and clean up actions.

For example, in the Sterling Windows Phone 7 Example I wrote (Sterling is an open source object-oriented database for Silverlight 4.0 and Windows Phone 7) I created a database service to make it easy to set up and tear down the database engine. The service looks like this:

public class DatabaseService : IApplicationService, IApplicationLifetimeAware
{
    public static DatabaseService Current { get; private set; }

    public ISterlingDatabaseInstance Database { get; private set; }

    private SterlingEngine _engine;
        
    public void StartService(ApplicationServiceContext context)
    {
            
        Current = this;
        _engine = new SterlingEngine();
    }

    public void StopService()
    {
        _engine = null;
    }

    public void Starting()
    {
        _engine.Activate();
        Database = _engine.SterlingDatabase.RegisterDatabase<PhoneDatabase>();
    }

    public void Started()
    {
        return;
    }

    public void Exiting()
    {
        _engine.Dispose();
    }

    public void Exited()
    {
        return;
    }
}

As you can see, I am managing everything that would normally get hooked into the application startup and exit events. Instead of adding to that code-behind, however, I can abstract these hooks in a re-usable component that is easily dropped into or out of the App.xaml as needed. Just like the previous example, the only thing needed to hook into the database in a Windows Phone 7 application is now just this:

<Application.ApplicationLifetimeObjects>
   <SterlingExample:SterlingService/>
</Application.ApplicationLifetimeObjects>

The Silverlight framework guarantees my service is called to start only once, so I take advantage of that call to assign a static property. That way, anywhere in the application I need to reference the service, I can use ServiceName.Current (for example, SterlingService.Current).

Don't limit yourself to just that, however. One common task in composite Silverlight applications is "bootstrapping" objects. If you are using the Managed Extensibility Framework (MEF), you may need to configure some catalogs and then call the CompositionInitializer. You can do this in an application service as well. In fact, many of my applications have nothing in the App.xaml.cs code behind except a call to InitializeComponent. Why? Because I can set the root visual in a service, like this:


[Import]
public Shell MainShell { get; set; }

public void StartService(ApplicationServiceContext context)
{
    _myCatalog = new AggregateCatalog(new DeploymentCatalog()); 
    var container = new CompositionContainer(_mainCatalog);
    CompositionHost.Initialize(container);              
    CompositionInitializer.SatisfyImports(this);
}

public void Starting()
{
    Application.Current.RootVisual = MainShell;
}

When called, the service sets up the catalogs/containers/etc. and satisfies imports to generate the shell. If the shell has any dependencies, these are also handled by MEF. Then, in the starting method, we wire the shell to the root visual because this is called just before the full visual tree is loaded.

I hope to see this powerful feature used more often to add some quality customer service to Silverlight applications.

Jeremy Likness

In this video, I wanted to share just how quick and easy it is to convert a Silverlight 3 project to Silverlight 4.

The steps are basically as follows:

  • Make sure you have the Silverlight 4 tools
  • If you use Blend or any of the interactivity extensions (for triggers and behaviors) be sure to get the latest version of Blend
  • If you use the Toolkit, download and install the latest version of that as well
  • Open your project in Visual Studio 2010, then
    1. Right-click the Silverlight projects, go into properties and change to target Silverlight 4
    2. Delete any bad Toolkit or Blend references and re-add them to point to the current version
    3. If you used the MEF preview, the references should update automatically — delete any local copies of the DLLs you may have included in the project
    4. Compile and run: in most cases, you're done!

In this simple example, I not only converted the application, but took advantage of the fact that buttons support commanding and removed a trigger I created in order to bind the button directly. Enjoy!

Jeremy Likness

Silverlight 4 provides some very powerful data form capabilities out of the box. You will no longer have to throw an exception just to send a validation error or even worry about hard-coding labels. With support for data annotations, IDataErrorInfo and more, you now have plenty "out of the box" to work with.

Let's explore the surface of some of these powerful new features!

IDataErrorInfo

With support for IDataErrorInfo as well as INotifyDataErrorInfo, you no longer have to raise exceptions just to validate your classes. Fire up VS 2010 and create a new Silverlight 4 application. First, we'll create a "helper" class to derive our entities from in order to perform validation and notify property changes. The class looks like this:


public abstract class BaseEntity : INotifyPropertyChanged, IDataErrorInfo
{
    private Dictionary<string, List<string>> _errors = new Dictionary<string, List<string>>();

    protected void RemoveErrors(string prop)
    {
        if (_errors.ContainsKey(prop))
        {
            _errors.Remove(prop);
        }
    }

    protected void AddError(string prop, string error)
    {
        if (_errors.ContainsKey(prop))
        {
            _errors[prop].Add(error);
        }
        else
        {
            _errors.Add(prop, new List<string> { error });
        }
    }

    protected void OnPropertyChanged(string prop)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(prop));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public virtual string Error
    {
        get { return string.Empty; }
    }

    public virtual string this[string columnName]
    {
        get 
        {
            System.Text.StringBuilder retVal = new System.Text.StringBuilder();

            if (_errors.ContainsKey(columnName))
            {
                bool first = true;
                foreach (string error in _errors[columnName])
                {
                    retVal.Append(error);
                    if (first)
                    {
                        first = false;
                    }
                    else
                    {
                        retVal.Append(Environment.NewLine);
                    }
                }
            }

            return retVal.ToString();
        }
    }
}

There are a few things going on here. First, we implement INotifyPropertyChanged in to facilitate binding. The protected OnPropertyChanged method allows derived classes to hook into this event.

Next, we implement IDataErrorInfo. This forces us to provide a single error property as well as an extension method that references errors for a given property. John Papa has an excellent article about building a handler for this at Enabling Validation in Silverlight 4 with IDataErrorInfo. In my case, I keep a dictionary referenced by the property name that holds a list in case there are multiple errors I want to show. When the errors are requested, I fold them into a single string using Environment.NewLine (OK, so the beta just came out the other day ... can't say I've fully tested that part).

Data Annotations

Now you can build a PersonInfo class based on this base class. To keep things simple for a contrived example, I chose just a first name, last name, and age. Here we'll need to add a reference to System.ComponentModel.DataAnnotations. You must install the latest Silverlight Toolkit for this. If you need to browse to it manually, it's located under the toolkit installation directory (usually c:\Program Files\Microsoft SDKs\Silverlight) under v4.0\Libraries\Client. Now we can derive the class and annotate it, like this:


public class PersonInfo : BaseEntity 
{
    private string _firstName, _lastName;

    private int _age;

    [Display(Name="First Name")]
    [Required]
    public string FirstName
    {
        get { return _firstName; }
        set
        {
            if (string.IsNullOrEmpty(value.Trim()))
            {
                AddError("FirstName", "First name is required.");
            }
            else
            {
                RemoveErrors("FirstName");
                if (!value.Equals(_firstName))
                {
                    _firstName = value;
                    OnPropertyChanged("FirstName");
                }
            }
        }
    }

    [Display(Name="Last Name")]
    [Required]
    public string LastName
    {
        get { return _lastName; }
        set
        {
            if (string.IsNullOrEmpty(value.Trim()))
            {
                AddError("LastName", "Last name is required.");
            }
            else
            {
                RemoveErrors("LastName");
                if (!value.Equals(_lastName))
                {
                    _lastName = value;
                    OnPropertyChanged("LastName");
                }
            }
        }
    }

    [Display(Name="Age (Years)")]
    [Required]
    public int Age
    {
        get { return _age; }
        set
        {
            if (value  130)
            {
                AddError("Age", "Age must be a valid integer between 18 and 130.");
            }
            else
            {
                RemoveErrors("Age");
                if (!value.Equals(_age))
                {
                    _age = value;
                    OnPropertyChanged("Age");
                }
            }
        }
    }
}

You'll probably pull out validations into a handler / rule set but basically what I'm doing is validating the value, setting an error or clearing all errors if it passes, then calling the property changed event if the value truly changes. Note the use of annotations to specify required properties as well as "friendly names" for the properties.

Now that our class is prepped, we can get to work on the XAML.

Implicit Styles

With support for implicit styles, we can set a style based on a target type and style it that way - allowing for themes to be set externally. We'll take advantage of that to set the width for our TextBox controls. I also add a reference to the PersonInfo class to use in data binding, so I won't need to touch the code-behind for MainPage.xaml:


<UserControl.Resources>
   <local:PersonInfo x:Key="Person"/>
   <Style TargetType="TextBox">
      <Setter Property="Width" Value="200"/>
   </Style>
</UserControl.Resources>

Data Input Helpers

Next, add a reference to System.Windows.Controls.Data.Input (found in the toolkit as well, same folder as the data annotations). We'll reference it at the top of our XAML (along with the local reference we need for the PersonInfo class:


xmlns:local="clr-namespace:DataForm"
    xmlns:dataInput="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.Input"

Great, now let's get to work! I'm going to show you the full snippet of XAML and then explain the pieces:


    <Grid x:Name="LayoutRoot" Background="White" DataContext="{Binding Source={StaticResource Person}}">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>           
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="Auto"/>
        </Grid.ColumnDefinitions>
        <dataInput:Label Target="{Binding ElementName=tbFirstName}"
                         Grid.Row="0" Grid.Column="0"/>
        <StackPanel Orientation="Horizontal" 
                    Grid.Row="0" Grid.Column="1">
            <TextBox x:Name="tbFirstName" 
                 Text="{Binding Path=FirstName, Mode=TwoWay, ValidatesOnDataErrors=True, NotifyOnValidationError=True, FallbackValue=''}"/>
            <dataInput:DescriptionViewer Description="Please enter your first name."
                                         Target="{Binding ElementName=tbFirstName}"/>
        </StackPanel>
        <dataInput:Label Target="{Binding ElementName=tbLastName}"
                         Grid.Row="1" Grid.Column="0"/>
        <StackPanel Orientation="Horizontal" 
                    Grid.Row="1" Grid.Column="1">
            <TextBox x:Name="tbLastName" 
                 Text="{Binding Path=LastName, Mode=TwoWay, ValidatesOnDataErrors=True, NotifyOnValidationError=True, FallbackValue=''}" />
            <dataInput:DescriptionViewer Description="Please enter your last name."
                                         Target="{Binding ElementName=tbLastName}"/>
        </StackPanel>
        <dataInput:Label Target="{Binding ElementName=tbAge}"
                         Grid.Row="2" Grid.Column="0"/>
        <StackPanel Orientation="Horizontal" 
                    Grid.Row="2" Grid.Column="1">
            <TextBox x:Name="tbAge" 
                     Text="{Binding Path=Age, Mode=TwoWay, ValidatesOnDataErrors=True, NotifyOnValidationError=True, FallbackValue='0'}"/>
            <dataInput:DescriptionViewer Description="Please enter a valid age between 18 and 130."
                                         Target="{Binding ElementName=tbAge}"/>
        </StackPanel>
        <dataInput:ValidationSummary Grid.Row="3" Grid.Column="0"
                                     Grid.ColumnSpan="2"/>        
    </Grid>

Some of these helper classes are made available via the toolkit for Silverlight 3 as well.

Labels

The label class lets us bind to an element like a textbox. It will pull the name of the databound property from the annotations and display it. If a validation error is thrown, it will turn red to further reinforce the error. If the field is tagged as required, the label will automatically bold itself to indicate a required field.

Learn more about the Label class

New Bindings

If you take a look at the textbox contorls, you'll see we've added new binding parameters. Specifically, ValidatesOnDataErrors (as opposed to exceptions) and FallbackValue (a value to use when databinding fails).

Learn more about bindings

Description Viewer

The description viewer control provides an easy way to show tips and hints and is similar to the ToolTip service. It will show an informational icon that, when the cursor hovers over, will provide a hint or description.

Learn more about the description viewer

Validation Summary

Finally, we add a validation summary control. The default behavior is to list all errors. When the user clicks on an error, it gives focus to the UI element that caused the error.

Learn more about the validation summary class

Putting it all Together

When you tie this all together and run it (without any additional code behind), this is an example of what you'll see:

Silverlight 4 Beta Data Forms

  • Note the labels automatically pulled from the DisplayAttribute on the entity class
  • The labels are bold due to the RequiredAttribute annotation
  • The labels on properties with errors are colored red
  • I clicked on the information glyph next to the first name text box and was the hint to enter my first name
  • I clicked on the red triangle in the upper right corner of the text box for age and was shown the error that my age is not in the valid range
  • The ValidationSummary control has summarized my errors (if I click on one, I'll be taken to the control with the issue)

As you can see, that's quite a bit of functionality right out of the box, and it allows a nice, clean separation of things like attributes and descriptions from the user interface that presents them.

Jeremy Likness

Earlier I explored some options to allow inline hyperlinks in Silverlight 3 using some extensions and the WrapPanel. In Silverlight 4, which was released as beta earlier this week, the problem is solved in the framework. Silverlight 4 gives us the RichTextArea control, which allows us to organize runs, spans, paragraphs, and even embed other UI elements to create a very richly illustrated document.

To illustrate this, I fired up a new Silverlight Application in Visual Studio 2010 and chose a Silverlight 4 application. Grabbing some more "lorem ipsum" text, I threw it into a RichTextArea control and then began embellishing with hyper links, formatting, and tossed in a red rectangle for good measure. The markup looks like this:


<RichTextArea TextWrapping="Wrap">
            <RichTextArea.Blocks>
                <Paragraph>Lorem ipsum dolor sit amet consectetur adipiscing elit.
                    <Bold>Suspendisse eu erat quis nibh laoreet hendrerit.</Bold>
                    <Italic>Tortor quam, auctor vel elementum et, rhoncus id augue.</Italic>
                    <Span Foreground="BlueViolet">Vestibulum nulla augue, dictum ut placerat et,</Span>
                    <Span>hendrerit a lorem. Vestibulum ante ipsum primis in</Span>
                    <Hyperlink NavigateUri="http://www.wintellect.com/"> faucibus orci luctus </Hyperlink>
                    <Run>et ultrices posuere cubilia Curae; Donec sollicitudin feugiat augue, eu 
                        vestibulum eros dapibus vel.
                    </Run>
                    <InlineUIContainer>
                        <Rectangle Width="20" Height="20" Stroke="Black" Fill="Red"/>
                    </InlineUIContainer>
                    Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.                  
                </Paragraph>
            </RichTextArea.Blocks>
            </RichTextArea>

As you can see, I am able to mix raw text, spans and runs that format colors or fonts, hyperlinks, and even use the InlineUIContainer to toss a rectangle into the mix. After building and publishing, this is what appears in the browser:

Rich text area in Silverlight 4 Beta

As you can see, a very serviceable rendering!

Next, we'll have a quick bit of fun. I add some row definitions and a header:


 <Grid.RowDefinitions>
             <RowDefinition Height="Auto"/>
             <RowDefinition/>
             <RowDefinition Height="Auto"/>
         </Grid.RowDefinitions>
         <TextBlock FontWeight="Bold" Grid.Row="0">Header

I wire the text area into row 1, then add this button to the last row:


  <Button Click="Button_Click" Content="Print" Grid.Row="2"/>

Do you get where I'm going? We don't want to print the header or the button, just the lorem ipsum section, so this is what we wire into the code behind:


public partial class MainPage : UserControl
{
    PrintDocument _pd; 

    public MainPage()
    {
        InitializeComponent();
        _pd = new PrintDocument();
        _pd.PrintPage += new EventHandler(pd_PrintPage);
    }

    void pd_PrintPage(object sender, PrintPageEventArgs e)
    {
        e.PageVisual = MainText;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        _pd.DocumentName = "Lorem Ipsum";
        _pd.Print();
    }
}

Note that we have three steps:

  1. Create a printing surface
  2. Trigger the print by calling the print method (and optionally setting some parameters)
  3. Wiring into the print event and setting the visual to print only what we want (keep in mind we could have created an entirely new set of UI elements here).

The new page looks like this:

Silverlight 4 Beta Print Button

When I click "print" I'm given the familiar print dialog. I selected the XPS writer and saved it as an XPS document. Here is the final result:

Silverlight 4 Beta Page Printed from Browser

I'll continue to follow how Silverlight 4 makes our life easier by integrating into the framework what we used to have to build ourselves!

Jeremy Likness