Using a ViewModel as a value converter

January 8, 2010

A recent post by Josh Twist shows how to support mingling code in XAML for WPF devs.  There have been several examples of putting code into XAML over the years, and they always raise the discussion of whether or not it is a good practice.  I am usually against having code in XAML because it makes it difficult to debug and maintain, but to each his/her own.  Regardless, that post got me thinking…

For a while now I’ve wondered how one might go about making it so that the little bits of code in the XAML might somehow be transplanted into the highly testable, debuggable, lovable world of the ViewModel.  Sure, you could put this type of logic into value converters, but writing a value converter that is only used once seems like a lot of extra work for little benefit.

Just for kicks, I decided to implement a class that would allow you to specify a method on your ViewModel object that contains the code that would otherwise be placed into a value converter, or in XAML.  The result is a markup extension I ever so lazily named BindingEx.  Here’s a simple usage:

Notice the last bit where the ConvertMethod property is set to AdjustTextWidth.  This is how you specify which method on the element’s VM should be invoked when the window’s width changes.  Here’s the VM class:

The TextViewModel object halves the window’s ActualWidth, and that value ends up being the width of the TextBlock.

I’m not sure that anyone should ever use this technique in a real application.  It’s probably a very stupid idea altogether, so I want to avoid any bad karma by stressing the point here:  USE AT YOUR OWN RISK!!

If you want to check out how I implemented BindingEx, click here to download the source code.  Be sure to change the file extension from .DOC to .ZIP and then decompress it.

Advertisement

The ultimate hack for Silverlight in Blend

January 6, 2010

I recently needed to write some design-time support for a Silverlight framework.  I needed to discover a solution’s assemblies while running in Blend, and then pass those assemblies downstream for further processing.  In WPF, using the full .NET framework, that’s easy: just call AppDomain.CurrrentDomain.GetAssemblies() and then filter them based on the Location property.  In Silverlight, however, a couple of problems showed up that seemed to make this task impossible.

First, the Assembly.Location property is marked ‘Security Critical’ in Silverlight 3.  This means that if you access the property, an exception will be thrown.

Second, Silverlight 3’s AppDomain class does not have a GetAssemblies method!

It turns out that both of these problems are easy to overcome.  The key thing to know is that when Silverlight code is running in Blend, it’s actually executing against the regular .NET Framework (the same one that WPF uses).  You can access ‘Security Critical’ members and no errors occur.  That takes care of the Assembly.Location issue.  Even though the Silverlight code you write, that is intended to run in Blend, can only access the Silverlight API, you can still access the full .NET framework’s API via reflection.  This allows you to work around the second issue.  For example:

var assemblies = typeof(AppDomain)
   .GetMethod("GetAssemblies")
   .Invoke(AppDomain.CurrentDomain, null);

Remember, this hack only works when your Silverlight code is running in Blend! This will not work when running under normal circumstances, since Silverlight apps normally only have access to the Silverlight subset of the .NET Framework.

Happy coding!