Scott Logic

Linq to Visual Tree

March 4th, 2010

This blog post demonstrates a Linq API which can be used to query the WPF / Silverlight Visual Tree. You can find a few other Linq to Visual Tree techniques on other blogs, but what makes this one unique is that it retains, and allows queries that make use of the tree like structure rather than simply flattening it.

I have recently published an article on codeproject which describes a technique for generating Linq API for querying tree-like structures. This blog post makes use of a generated API for WPF / Silverlight. If you are interested in the more generic approach, and how this API was constructed, (and how it is influenced by XPath) head on over to codeproject …

What I will provide here is a brief overview of the Linq to Visual Tree API. The full sourcecode for this API is at the end of this article.

The Linq to Visual Tree API defines a number of extension methods on DependencyObject that provide mechanisms for navigating to other DependencyObject instances. I will provide a few examples that query the following simple markup:

<Grid x:Name="GridOne" Background="White">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>
 
    <TextBox x:Name="TextBoxOne" Text="One" Grid.Row="0" />
 
    <StackPanel x:Name="StackPanelOne" Grid.Row="1">
        <TextBox x:Name="TextBoxTwo" Text="Two" />
 
        <Grid x:Name="GridTwo">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
 
            <TextBox x:Name="TextBoxThree" Text="Three" Grid.Row="0" />
 
            <StackPanel x:Name="StackPanelTwo" Grid.Row="1">
                <TextBox x:Name="TextBoxFour" Text="Four"/>                    
            </StackPanel>
        </Grid>
    </StackPanel>
</Grid>

We’ll start with a simple example. Include the Linq to Visual Tree namespace, then use the Descendants method to obtain all the descendants (i.e. children and children’s children, etc …) of an object within the
visual tree.

Descendants

using LinqToVisualTree;
 
// all items within the visual tree
IEnumerable<DependencyObject> allDescendants = this.Descendants();
/*
gives ...
0 {Grid} 	[GridOne]
1 {TextBox} 	[TextBoxOne]
2 {StackPanel} 	[StackPanelOne]
3 {TextBox} 	[TextBoxTwo]
4 {Grid} 	[GridTwo]
5 {TextBox} 	[TextBoxThree]
6 {StackPanel} 	[StackPanelTwo]
7 {TextBox} 	[TextBoxFour]
*/
 
// all items within the visual tree of 'GridTwo'
var descendantsOfGridTwo = GridTwo.Descendants();
/*
gives ...
0 {TextBox} 	[TextBoxThree]
1 {StackPanel} 	[StackPanelTwo]
2 {TextBox} 	[TextBoxFour]
*/

Each of the extension methods also has a corresponding method with a generic type parameter that filters the collection to find elements of a specific type:

// all items within the visual tree of 'GridTwo' that are textboxes
var textBoxDescendantsOfGridTwo = GridTwo.Descendants()
                                         .Where(i => i is TextBox);
/*
0 {TextBox} 	[TextBoxThree]
1 {TextBox} 	[TextBoxFour]
*/
 
// a shorthand using the generic version of Descendants
var textBoxDescendantsOfGridTwo2 = GridTwo.Descendants<TextBox>();
/*
0 {TextBox} 	[TextBoxThree]
1 {TextBox} 	[TextBoxFour]
*/

Elements

The elements extension method obtains all the direct children of an item in the visual tree:

// find all direct children of this user control 
var userControlChildren = this.Elements();
/*
0 {Grid} 	[GridOne]
*/
 
// find all direct children of the grid 'GridTwo'
var gridChildren = GridTwo.Elements();
/*
0 {TextBox} 	[TextBoxThree]
1 {StackPanel} 	[StackPanelTwo]
*/
 
// find all direct children of the grid 'GridTwo' that are StackPanels
var gridChildren2 = GridTwo.Elements<StackPanel>();
/*
0 {StackPanel} 	[StackPanelTwo]
*/

There are also, ElementsBeforeSelf and ElementsAfterSelf methods that return the elements before and after the item which the method is being invoked upon.

Ancestors

The ancestors methods traverse the tree towards the root, finding all the ancestors:

// the ancestors for 'TextBoxFour'
var ancestors = TextBoxFour.Ancestors();
/*
0 {StackPanel} 	[StackPanelTwo]
1 {Grid} 	[GridTwo]
2 {StackPanel} 	[StackPanelOne]
3 {Grid} 	[GridOne]
4 {MainPage} 	[]
*/
 
// the ancestors for 'TextBoxFour' that are StackPanels
var stackPanelAncestors = TextBoxFour.Ancestors<StackPanel>();
/*
0 {StackPanel} 	[StackPanelTwo]
1 {StackPanel} 	[StackPanelOne]
*/

Putting it all together

The Linq to Tree API not only defines extension methods on DependencyObject, but also the same extension methods on IEnumerable<DependencyObject>. Unless you have previous experience of Linq to XML, I would strongly suggest reading my codeproject article to understand how this works!

This allows you to form much more complex queries. For example, you can find all TextBoxs that have a Grid as a direct parent:

var itemsFluent = this.Descendants<TextBox>()
                      .Where(i => i.Ancestors().FirstOrDefault() is Grid);
 
var itemsQuery = from v in this.Descendants<TextBox>()
                 where v.Ancestors().FirstOrDefault() is Grid
                 select v;
/*
0 {TextBox} 	[TextBoxOne]
1 {TextBox} 	[TextBoxThree]
*/

Here, you can also see we are mixing the fluent and query syntax for Linq. Both give the same result.

The next example finds all StackPanels that are within another StackPanels visual tree:

var items2Fluent = this.Descendants<StackPanel>()
                              .Descendants<StackPanel>();
 
var items2Query = from i in
                      (from v in this.Descendants<StackPanel>()
                       select v).Descendants<StackPanel>()
                  select i;
/*
0 {StackPanel} 	[StackPanelTwo]
*/

Finally, this one-liner, outputs the entire visual tree in ASCII! It makes use of the DescendantsAndSelf, Ancestors and ElementsBeforeSelf methods, plus the funky Linq Aggregate method.

string tree = this.DescendantsAndSelf().Aggregate("",
    (bc, n) => bc + n.Ancestors().Aggregate("", (ac, m) => (m.ElementsAfterSelf().Any() ? "| " : "  ") + ac,
    ac => ac + (n.ElementsAfterSelf().Any() ? "+-" : "\\-")) + n.GetType().Name + "\n");
\-MainPage
  \-Grid
    +-TextBox
    | \-Grid
    |   +-Border
    |   | \-Grid
    |   |   +-Border
    |   |   \-Border
    |   |     \-ScrollViewer
    |   |       \-Border
    |   |         \-Grid
    |   |           +-ScrollContentPresenter
    |   |           | \-TextBoxView
    |   |           +-Rectangle
    |   |           +-ScrollBar
    |   |           \-ScrollBar
    |   +-Border
    |   +-Border
    |   \-Border
    |     \-Grid
    |       +-Path
    |       \-Path
    \-StackPanel
      +-TextBox
      | \-Grid
      |   +-Border
      |   | \-Grid
      |   |   +-Border
      |   |   \-Border
      |   |     \-ScrollViewer
      |   |       \-Border
      |   |         \-Grid
      |   |           +-ScrollContentPresenter
      |   |           | \-TextBoxView
      |   |           +-Rectangle
      |   |           +-ScrollBar
      |   |           \-ScrollBar
      |   +-Border
      |   +-Border
      |   \-Border
      |     \-Grid
      |       +-Path
      |       \-Path
      \-Grid
        +-TextBox
        | \-Grid
        |   +-Border
        |   | \-Grid
        |   |   +-Border
        |   |   \-Border
        |   |     \-ScrollViewer
        |   |       \-Border
        |   |         \-Grid
        |   |           +-ScrollContentPresenter
        |   |           | \-TextBoxView
        |   |           +-Rectangle
        |   |           +-ScrollBar
        |   |           \-ScrollBar
        |   +-Border
        |   +-Border
        |   \-Border
        |     \-Grid
        |       +-Path
        |       \-Path
        \-StackPanel
          \-TextBox
            \-Grid
              +-Border
              | \-Grid
              |   +-Border
              |   \-Border
              |     \-ScrollViewer
              |       \-Border
              |         \-Grid
              |           +-ScrollContentPresenter
              |           | \-TextBoxView
              |           +-Rectangle
              |           +-ScrollBar
              |           \-ScrollBar
              +-Border
              +-Border
              \-Border
                \-Grid
                  +-Path
                  \-Path

Note: this was invoked after the LayoutUpdated event so that we not only see the elements from our XAML, but also the elements created from their templates, giving us our full run-time visual tree.

You can download a simple Silverlight application that demonstrated all the examples given above:
LinqToTree.zip.

Or, if you just want the Linq to VisualTree code, you can copy-n-paste from the windows below which has the entire API, which includes the methods illustrated above,, plus their IEnumerable equivalents, and a few others I have not illustrated.

using System;
using System.Linq;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;

namespace LinqToVisualTree
{
    /// 
    /// Adapts a DependencyObject to provide methods required for generate
    /// a Linq To Tree API
    /// 
    public class VisualTreeAdapter : ILinqTree
    {
        private DependencyObject _item;

        public VisualTreeAdapter(DependencyObject item)
        {
            _item = item;
        }

        public IEnumerable Children()
        {
            int childrenCount = VisualTreeHelper.GetChildrenCount(_item);
            for (int i = 0; i < childrenCount; i++)
            {
                yield return VisualTreeHelper.GetChild(_item, i);
            }
        }

        public DependencyObject Parent
        {
            get
            {
                return VisualTreeHelper.GetParent(_item);
            }
        }
    }
}

namespace LinqToVisualTree
{
    /// 
    /// Defines an interface that must be implemented to generate the LinqToTree methods
    /// 
    /// 
    public interface ILinqTree
    {
        IEnumerable Children();

        T Parent { get; }
    }

    public static class TreeExtensions
    {
        /// 
        /// Returns a collection of descendant elements.
        /// 
        public static IEnumerable Descendants(this DependencyObject item)
        {
            ILinqTree adapter = new VisualTreeAdapter(item);
            foreach (var child in adapter.Children())
            {
                yield return child;

                foreach (var grandChild in child.Descendants())
                {
                    yield return grandChild;
                }
            }
        }

        /// 
        /// Returns a collection containing this element and all descendant elements.
        /// 
        public static IEnumerable DescendantsAndSelf(this DependencyObject item)
        {
            yield return item;

            foreach (var child in item.Descendants())
            {
                yield return child;
            }
        }

        /// 
        /// Returns a collection of ancestor elements.
        /// 
        public static IEnumerable Ancestors(this DependencyObject item)
        {
            ILinqTree adapter = new VisualTreeAdapter(item);

            var parent = adapter.Parent;
            while (parent != null)
            {
                yield return parent;
                adapter = new VisualTreeAdapter(parent);
                parent = adapter.Parent;
            }
        }

        /// 
        /// Returns a collection containing this element and all ancestor elements.
        /// 
        public static IEnumerable AncestorsAndSelf(this DependencyObject item)
        {
            yield return item;

            foreach (var ancestor in item.Ancestors())
            {
                yield return ancestor;
            }
        }

        /// 
        /// Returns a collection of child elements.
        /// 
        public static IEnumerable Elements(this DependencyObject item)
        {
            ILinqTree adapter = new VisualTreeAdapter(item);
            foreach (var child in adapter.Children())
            {
                yield return child;
            }
        }

        /// 
        /// Returns a collection of the sibling elements before this node, in document order.
        /// 
        public static IEnumerable ElementsBeforeSelf(this DependencyObject item)
        {
            if (item.Ancestors().FirstOrDefault() == null)
                yield break;
            foreach (var child in item.Ancestors().First().Elements())
            {
                if (child.Equals(item))
                    break;
                yield return child;
            }
        }

        /// 
        /// Returns a collection of the after elements after this node, in document order.
        /// 
        public static IEnumerable ElementsAfterSelf(this DependencyObject item)
        {
            if (item.Ancestors().FirstOrDefault() == null)
                yield break;
            bool afterSelf = false;
            foreach (var child in item.Ancestors().First().Elements())
            {
                if (afterSelf)
                    yield return child;

                if (child.Equals(item))
                    afterSelf = true;
            }
        }

        /// 
        /// Returns a collection containing this element and all child elements.
        /// 
        public static IEnumerable ElementsAndSelf(this DependencyObject item)
        {
            yield return item;

            foreach (var child in item.Elements())
            {
                yield return child;
            }
        }

        /// 
        /// Returns a collection of descendant elements which match the given type.
        /// 
        public static IEnumerable Descendants(this DependencyObject item)
        {
            return item.Descendants().Where(i => i is T).Cast();
        }

        /// 
        /// Returns a collection of the sibling elements before this node, in document order
        /// which match the given type.
        /// 
        public static IEnumerable ElementsBeforeSelf(this DependencyObject item)
        {
            return item.ElementsBeforeSelf().Where(i => i is T).Cast();
        }

        /// 
        /// Returns a collection of the after elements after this node, in document order
        /// which match the given type.
        /// 
        public static IEnumerable ElementsAfterSelf(this DependencyObject item)
        {
            return item.ElementsAfterSelf().Where(i => i is T).Cast();
        }

        /// 
        /// Returns a collection containing this element and all descendant elements
        /// which match the given type.
        /// 
        public static IEnumerable DescendantsAndSelf(this DependencyObject item)
        {
            return item.DescendantsAndSelf().Where(i => i is T).Cast();
        }

        /// 
        /// Returns a collection of ancestor elements which match the given type.
        /// 
        public static IEnumerable Ancestors(this DependencyObject item)
        {
            return item.Ancestors().Where(i => i is T).Cast();
        }

        /// 
        /// Returns a collection containing this element and all ancestor elements
        /// which match the given type.
        /// 
        public static IEnumerable AncestorsAndSelf(this DependencyObject item)
        {
            return item.AncestorsAndSelf().Where(i => i is T).Cast();
        }

        /// 
        /// Returns a collection of child elements which match the given type.
        /// 
        public static IEnumerable Elements(this DependencyObject item)
        {
            return item.Elements().Where(i => i is T).Cast();
        }

        /// 
        /// Returns a collection containing this element and all child elements.
        /// which match the given type.
        /// 
        public static IEnumerable ElementsAndSelf(this DependencyObject item)
        {
            return item.ElementsAndSelf().Where(i => i is T).Cast();
        }

    }

    public static class EnumerableTreeExtensions
    {
        /// 
        /// Applies the given function to each of the items in the supplied
        /// IEnumerable.
        /// 
        private static IEnumerable DrillDown(this IEnumerable items,
            Func> function)
        {
            foreach (var item in items)
            {
                foreach (var itemChild in function(item))
                {
                    yield return itemChild;
                }
            }
        }

        /// 
        /// Applies the given function to each of the items in the supplied
        /// IEnumerable, which match the given type.
        /// 
        public static IEnumerable DrillDown(this IEnumerable items,
            Func> function)
            where T : DependencyObject
        {
            foreach (var item in items)
            {
                foreach (var itemChild in function(item))
                {
                    if (itemChild is T)
                    {
                        yield return (T)itemChild;
                    }
                }
            }
        }

        /// 
        /// Returns a collection of descendant elements.
        /// 
        public static IEnumerable Descendants(this IEnumerable items)
        {
            return items.DrillDown(i => i.Descendants());
        }

        /// 
        /// Returns a collection containing this element and all descendant elements.
        /// 
        public static IEnumerable DescendantsAndSelf(this IEnumerable items)
        {
            return items.DrillDown(i => i.DescendantsAndSelf());
        }

        /// 
        /// Returns a collection of ancestor elements.
        /// 
        public static IEnumerable Ancestors(this IEnumerable items)
        {
            return items.DrillDown(i => i.Ancestors());
        }

        /// 
        /// Returns a collection containing this element and all ancestor elements.
        /// 
        public static IEnumerable AncestorsAndSelf(this IEnumerable items)
        {
            return items.DrillDown(i => i.AncestorsAndSelf());
        }

        /// 
        /// Returns a collection of child elements.
        /// 
        public static IEnumerable Elements(this IEnumerable items)
        {
            return items.DrillDown(i => i.Elements());
        }

        /// 
        /// Returns a collection containing this element and all child elements.
        /// 
        public static IEnumerable ElementsAndSelf(this IEnumerable items)
        {
            return items.DrillDown(i => i.ElementsAndSelf());
        }

        /// 
        /// Returns a collection of descendant elements which match the given type.
        /// 
        public static IEnumerable Descendants(this IEnumerable items)
            where T : DependencyObject
        {
            return items.DrillDown(i => i.Descendants());
        }

        /// 
        /// Returns a collection containing this element and all descendant elements.
        /// which match the given type.
        /// 
        public static IEnumerable DescendantsAndSelf(this IEnumerable items)
            where T : DependencyObject
        {
            return items.DrillDown(i => i.DescendantsAndSelf());
        }

        /// 
        /// Returns a collection of ancestor elements which match the given type.
        /// 
        public static IEnumerable Ancestors(this IEnumerable items)
            where T : DependencyObject
        {
            return items.DrillDown(i => i.Ancestors());
        }

        /// 
        /// Returns a collection containing this element and all ancestor elements.
        /// which match the given type.
        /// 
        public static IEnumerable AncestorsAndSelf(this IEnumerable items)
            where T : DependencyObject
        {
            return items.DrillDown(i => i.AncestorsAndSelf());
        }

        /// 
        /// Returns a collection of child elements which match the given type.
        /// 
        public static IEnumerable Elements(this IEnumerable items)
            where T : DependencyObject
        {
            return items.DrillDown(i => i.Elements());
        }

        /// 
        /// Returns a collection containing this element and all child elements.
        /// which match the given type.
        /// 
        public static IEnumerable ElementsAndSelf(this IEnumerable items)
            where T : DependencyObject
        {
            return items.DrillDown(i => i.ElementsAndSelf());
        }
    }
}

Regards, Colin E.

Using built-in, embedded and streamed fonts in Silverlight

March 1st, 2010
Silverlight gives the developer the possibility of completely customizing the developed application in all aspects. Defining fonts used for displaying text is no exception. However there are multiple ways on how to go ahead with specifying fonts to use, this article attempts to summarize the options. Using built-in fonts Silverlight comes with some fonts that can [...]

My Mix10k entry – Old Skool demo – plus a few tips

January 7th, 2010

This blog post is about my entry to the Mix10k code competition, and old-skool demo, plus a few tips about how to keep you code size to below 10k.

The mix10k challenge, where you are given 10k to create a Silverlight / HTML5 application, has been on my mind for a while … the Christmas vacation was the perfect excuse to put together my entry. Inspired by the demo’s of the Amiga era, here is my mix10k old-skool demo entry:

You can view my entry (and more importantly vote for it!) at the mix10k gallery.

For me the greatest challenge was the music, not least for the fact that I am no good at writing the stuff myself! The mix10k rules are fairly relaxed, you can download content, such as images and music, allowing you to circumnavigate the 10k limit. However, I thought it would be a more interesting challenge to pack everything into 10k.

Size-limited demos typically use synthesis rather than sampling for the musics. Unfortunately Silverlight isn’t really geared towards sound synthesis, however, a few people have managed to create synthesized media sources. I decided to go the sampling route and use an MP3 track for my music, the idea being to use a short, highly compressed MP3 track and loop it. I posted a message on the 8bitcollective forums and within a day had a funky, and highly compressed, 4 second MP3 clip for my demo. The MP3 filesize of 4,248 bytes left me 5,992 to play with.

However, the next challenge was looping the audio, which is unfortunately something that is not supported out-of-the-box. For longer media clips it is acceptable to catch the MediaEnded event, re-wind and re-start. However, there is a delay of about half a second, which with a 4 second looped audio clip is pretty disruptive! Fortunately Silverlight does expose a lower level API for media via the abstract class MediaStreamSource, which has virtual methods which you can override to supply audio direct from a stream. The codeplex project ManagedMediaHelpers is a great place to start for information on how to load MP3 audio from a file. Typically the code to read and stream an MP3 file is over 10k, however, I was able to trim this down to roughly 1k by removing all the code for parsing the MP3 headers, replacing it with the hard-coded values for my specific MP3 file.

Unfortunately, when the audio was looped, it just didn’t sound right. The trouble is, within MP3 files, the audio is split into frames. Using a useful utility from codeproject, I found that my MP3 file consisted of 56 frames of ~67ms in length. However, the audio loop was not a multiple of 67ms. To rectify this, I downloaded a copy of the free audio editor Audacity, and ’stretched’ the track to fit into an integer number of frames, and re-encoded in MP3 format via lame. Finally, I had looping MP3 audio! (and 4,958 bytes left)

audacity

After the battle I had with the audio, constructing the visuals, the scrolling text, interference patterns, plasma and starfield was a piece of cake!

Here are a few quick tips for keeping your filesize under 10k.

  • Use the var keyword wherever possible
     
  • Use the using for aliasing frequently used types

    For example:

    using K = System.Windows.Media.MediaSourceAttributesKeys;
    using J= System.Windows.Media.MediaStreamAttributeKeys;
    using M = System.Math;

    With type names as long as MediaSourceAttributesKeys, you only need to use them three times for a using alias to make sense!

  • chain initialisation of variables

    The following code:

    int x1 = sin1(8) + 200
    int y1 = sin1(3) * 10 + 100
    int g = (tx - x1) * (tx - x1);

    Can be shortened to:

    int x1 = sin1(8) + 200, y1 = sin1(3) * 10 + 100, g = (tx - x1) * (tx - x1);
  • Tabs not spaces

    If you are not to bothered about squeezing the most out of those 10k bytes and want your code to look pretty, at least save yourself a bit of room by using Tabs!

  • Choose wisely between XAML and C#

    One big advantage that XAML has over C# is its use of value converters, compare the following XAML:

    <Ellipse Fill="White"/>

    to its equivalent in C#:

    var el = new Ellipse()
    {
       Fill = new SolidColorBrush(Color.FromArgb(255,255,255,255))
    };

    In this case, XAML is a clear winner.

  • Use lambda expressions for event handlers

    You can achieve great savings by including your event handling logic within anonymous delegates (via lambda expressions), it also means that you can move variables from class scope (i.e. files) to method scope and use the var keyword. Compare:

    WriteableBitmap bitmap = new WriteableBitmap(200,200);
     
    MyPage()
    {
    	var t = new DispatcherTimer();
    	t.Tick +=new EventHandler(t_Tick);
    }
     
    void  t_Tick(object sender, EventArgs e)
    {
    	// do stuff with the bitmap
    	bitmap.Invalidate();
    }

    to:

    MyPage()
    {
    	var bitmap = new WriteableBitmap(200,200);
    	var t = new DispatcherTimer();
    	t.Tick += (s,e) =>
    		{
    			// do stuff with the bitmap
    			bitmap.Invalidate();
    		};
    }
  • Ditch that App!

    The App.xaml and App.xaml.cs full of template code that you do not need. Simply ditch these files entirely and replace with a minimal application that indicates the page to display:

    public class A : Application
    {
        public A()
        {
            Startup += (i, j) => RootVisual = new MainPage();
        }
    }
  • Minify your code

    Perhaps the greatest savings can be achieved by ‘minifying’ your code, i.e. removing any extra whitespace and reducing variable, method, types names to single characters. The problem is that in doing so, your code will become unreadable!

    In order to minify my code yet maintain readability I created a very simple console application that read my application source and performed a bunch of string replacements in order to reduce its size …

    static Dictionary<string, string> reps = new Dictionary<string, string>()
    {
      {System.Environment.NewLine, ""}, 
      {"  ", " "},
      {" = ", "="},
      {" == ", "=="},
      {" * ", "*"},
      {" > ", ">"},
      {" < ", "<"},
      ...
     
      // methods 
      {"Timer_Tick", "T"},
      {"CreateLine", "g"},
      {"DrawLines", "ln"},
      ...
     
      // xaml
      {"grid", "q"},
      {"image", "o"},
      {"canvas", "c"},
      {"MainPage", "Y"},
      ...
    };

    The output of this console application is sent to another project which builds my final entry. The result of this was to make my reasonably compact code 47% smaller!

You can download my thoroughly messy and unreadable code: mix10ksrc.zip

And vote for it on the mix10k site (Did I say that already?)

Regards, Colin E.

Silverlight 4 beta released leaving Flex behind

November 19th, 2009
This post looks at the speed of development of the two leading RIA frameworks, Silverlight and Flex, giving unequivocal proof that Silverlight is better than Flex … ! This week at Microsoft’s Professional Developers Conference (PDC), there have been two big news stories. The first is the give-away of a free tablet PC to all attendees, and [...]

The mini-ViewModel pattern

August 7th, 2009
The construction of a ViewModel is often seen as the standard technique for solving binding problems within WPF and Silverlight. However, the addition of a ViewModel adds complexity to your code. This post describes an alternative method where a mini-ViewModel is applied directly to the problem areas in the view, leaving the rest to use [...]

News on Silverlight adoption from the Silverlight 3 UK Launch

July 23rd, 2009
Yesterday myself and Gary Scott (our MD) went down to London for the Silverlight 3 UK launch event. This is the first time I have been to Microsoft’s London office so I wasn’t quite sure what to expect. The glass-clad arched office exterior, and shiny minimalist interior were certainly stylish, however I was a bit [...]

Silverlight v3 ClearType Font Rendering – A comparison

July 14th, 2009
Text rendering has been a problem for both Silverlight and WPF for a while. This blog post looks at ClearType in Silverlight v3 and compares it to WPF and WinForms text rendering. Text clarity is something that concerns me quite a bit. In financial applications, such as our market overview pages, often large quantities of both [...]

Silverlight 3 UK launch … and the future of WPF?

July 9th, 2009
A brief article on the launch of Silverlight 3 and why the interest in Silverlight is eclipsing that of WPF. The excitement behind Silverlight has been gaining in momentum throughout this year, with one of the highpoints being the MIX09 conference in March this year where the announcement of Silverlight 3 beta took centre stage. There [...]

Exposing Bindings as Properties of a Control

June 19th, 2009
I must admit that the title of this post is not entirely clear, however I couldn’t find a way to sum up the content in one short sentence, so we’ll dive straight into an example. Let’s say for example you have developed a funky little business-card as illustrated above, using the simple XAML below: <Border BorderBrush="LightGray" [...]

Dependency Property Performance and Lissajous Figures

June 2nd, 2009
A few night ago I was working on a Siverlight control which renders some quite complex Paths, the geometry of which is determined from a number of dependency properties. In order to gain UI coolness points I wanted to animate the dependency properties in order to see a smooth transition of the Path [...]