When you are performing code generation and you would like to dynamically create some UI stuff it into a ContentPresenter, the XamlReader class comes to the rescue. However, if you have any events that you would like to handle in your newly composed Xaml, the XamlReader class will throw an exception stating that no event handlers can be present. I use code generation quite extensively in my applications when I have scenarios that I need user driven interfaces. Thus, it is important to be able to have the flexibility to create Xaml on the fly and still have all the power of interacting with any event that the new UI contains as needed.
Here is a sample of Xaml taht will throw an exception when loaded by the XamlReader class:
One of the nice features that we have had since Silverlight 3 is the ability to define behaviors and triggers using a set pattern. The good thing about this is that these behaviors and triggers are not evaluated until the given control is loaded in the VisualTree. This is good because now we have a solution that will allow us to use the XamlReader class that has event handlers and the class does not throw an exception.
Here is a snippet of some Xaml that is created on the fly:
So the next time you are wanting to do some dynamic UI generation but also want to process events, you now have the tools to let you do so. As an added bonus, the triggers will fire on whatever DataContext the UI is a part of. This is nice because it supports a clean separation of concerns and follows the common Model-View-ViewModel (MVVM) pattern.
This is going to be a very short post on something that took much too long to debug. I have been working on a dynamic framework for Dashboarding in Silverlight. Silverlight, currently, does not support DataSet or DataTable objects. So, I decided that I wanted to mimic basically what the rest of the .NET world had access to in Silverlight. It turns out that one of the property in the DataColumn class exposes a DataType property of System.Type. This was a very nasty problem because if I debugged the WCF Service on the server, everything worked fine but as soon as I tried to return the service to the client…everything went wrong and the browser blurted out the wise and sagacious message “Server not found!”. Now this is not very helpful but it turns out a very good friend of mine had a suggestion of trying to serialize my result in my service method before actually returning it. This, basically, gave me the opportunity to see what was happening black box from WCF. Viola! The culprit was my friendly System.Type public property. WCF does not allow serialization of this type and I had to serialize the name of the type and the create the type on the client in order for my DataTable implementation to work.
The simple solutions is a washout compared to the length of time I spent trying to troubleshoot the browser messages I was getting. So, if you see a funny error and you know that the code is working correctly on the server…chances are that you have a serialization error or a size limit being met if it is a big object graph.
The other day I was catching up on some of Dan Wahlin’s posts and I read his post about providing a DataContext to controls that needed to access the ViewModel but were in a sub-collection. He went through some good approaches as to how one could go about solving this problem.
I would like to also offer up another approach that is quite similar to his but with a twist. I agree that, if possible, it keeps things simple if you can provide a way to reach out to the underlying ViewModel no matter what the nesting level your control resides in. In my experience, I rarely find a solution that works best for all of my scenarios but I have found several solutions that tend to handle most of the the issues I come across.
Before we go further, I would like to present the general approach that I use to build these solutions. I use Behaviors. These guys live in the System.Windows.Interactivity namespace. They provide a very powerful way to write code once and use over and over in your Xaml.
I will present them first in a list and then provide a detailed explanation when each would be used:
- DataContextToDomainDataSourceBehavior — this behavior exposes a property, “ControlName”. It uses this to walk up the Visual Tree until it finds such a control and then sets the DataContext of the underlying control for which this behavior is set. The DataContext gets set on the Loaded event.
- ItemSourceBehavior — This behavior has a lot of flexibility. It exposes “ItemsSourceName”, “IsEnum”, “EnumFilter” properties. This behavior works on any ItemsControl, DataGrid, and Telerik RadGridView. If the IsEnum flag is set, then it is smart enough to set the ItemsSource to the named enum. Otherwise, it will find the named property on the DataContext. This behavior explicitly looks for the first UserControl it can find and grabs its DataContext.
- ItemSourceBindingBehavior — This is basically the same as the previous behavior but this one binds the ItemsSource to the underlying property. This facilitates for a more MVVM style of programming.
- ItemSourceToDomainDataSourceBehavior — This fires on the loaded event and has a property that holds the name of a DomainDataSource. This behviour explicitly looks for the first UserControl it can find and then looks for a DomainDataSource with the given name. If it finds it then ItemSource property is bound to the DomainDataSource. This happens for ItemsControls and the DataGrid.
Each of these behaviors performs a specific task and has certain capabilities. As you can see, there may be scenarios that you could use that are not exposed by what I have show here. I will go further into how these work in a later post.
If you are you are going to CodeStock 2010, please register and vote for my two sessions:
- Building Business Application with Silverlight (2 hour session) – lots of content to present.
- What’s new in Silverlight 4?
You can register by clicking on the following link: http://codestock.org
One of the painful problems that I have encountered recently is trying to port our applications from Silverlight 4 Beta 2 to Silverlight 4 RC using Visual Studio 2010 RC. It has been a very excruciating process. Everytime I try and compile what worked perfectly fine in Visual Studio 2010 Beta 2 for Silverlight 4 now crashes Visual Studio 2010 RC. I have found at least one work around that just very may well keep my sanity until Visual Studio 2010 is released on April 12, 2010.
The following are the steps I took to be able to build my applications:
- I used Blend 4 Beta! Blend 4 will compile all of my projects and applications that are currently crashing Visual Studio 2010.
- I have noticed that I have to Clean and then ReBuild the solution in Blend 4, I can (most of the time) then run the application in Debug mode in Visual Studio 2010. This is very important since I constantly changing code and wanting to test and debug.
That is it! It isn’t sexy but it does get the job done. I have submitted my Visual Studio 2010 logs to Microsoft as a bug and I am hoping that I will get a response from them as to what it might be.
Until next time, stay tuned….