Tuesday, June 28, 2011

SilverlightToolkit Development/Building Guidance

If you're like me and want to alter some of Silverlight Toolkit's behavior (or add more functionality to it), chances are your builds will not work perfectly and you'll be in a constant state of mismatched assemblies.

I've noticed that Silverlight Toolkit has some major issues with the entire build process -- only loading different components and making references to other DLL's (which get deleted if you perform a clean build), not other projects.  The second those are removed from the Binaries directory, the entire system goes to hell and back, eventually grabbing references to your DLL's in the Silverlight Toolkit install directory (somewhere in your root drive under Program Files, etc).  What a pain!  Then you'd have to go back and rebuild the references and re-specify their location.  There has to be a better way, right?

Kind of.

What I ended up doing, and I highly recommend this for anyone working with Silverlight Toolkit on a regular basis -- is to build a new solution, rather than use the existing ones.  Don't worry about including their Design or Testing projects, unless they're important to you.  Then follow this process:

1. Build a new solution and include all relevant projects.
As stated before, place everything that you actually care about building.  In my case, I was only concerned about the actual controls - not the testing or design.  Since I'm already heavily involved with using the controls, I'll know if they're broken in test or design scenarios.
2. (Optional) Rename all projects to their full assembly name, rather than a shorthand version.
When viewing their projects, you'll notice things like Controls.Data or System.Controls, which are all very misleading.  Everything falls under System.Windows.*.  For sake of clarity, I found myself renaming them, so when I would eventually add references back to other projects, I could see the full name of the project/assembly built.
3. Change build path in each project, for all build-types, to a single directory.
You'd be surprised how many different places the assemblies for Silverlight Toolkit get built to.  Each project seems to be written by someone else, with their own styles/paths for where assemblies that are built get stored.  I simplified everything and made everything build to the Binaries folder -- always. 
 4. Referenced assemblies from other SDKs should be placed in a special folder under the build path.
This is a pattern we have at work -- if you build something that requires a reference to an SDK other than our own, you drop the assembly in a References project and store everything in source control for the entire team to use.  You won't have to install the toolkits for other team members at this point, since they'll be in a standard location.  For Design and Testing projects, SilverlightToolkit uses other SDKs, so this is vital for those of you wishing to build these.
5. Remove all references to SilverlightToolkit projects and re-add them as a reference to the projects in your solution.
As stated before, the references all get built to different places, which can cause for some crazy issues when you perform a clean.  They then default back to your SilverlightToolkit install.  It's horribly complicated.  Referencing your projects will create appropriate dependencies that cause everything to build correctly and together.  You can imagine what will happen to System.Windows.Controls.DataVisualizations when it tries to reference System.Windows.Controls and the assemblies are built at different times with different dependencies.  If you can't, imagine shear sacrilege.  And pain.  And suffering.
If you follow these guidelines, you should have a much more stable/clean build of SilverlightToolkit, which will make future developments and enhancements easier to bake in (such as targeting a WPF platform for Charting).  Unfortunately SilverlightToolkit also no longer accepts user contributions, due to licensing issues, and Microsoft is the sole development team.  This makes getting features added a little (read: very) difficult.

Good luck and happy building!

Monday, June 27, 2011

VisualTreeHelper - Your New Best Friend

Ever noticed that WPF and Silverlight don't like to play nicely with their implementations of the same controls?  Often, this is because they are derived differently.  They both ultimately derive from DependencyObject, however the

In any case, the VisualTreeHelper is your best friend when it comes to navigating the structure of your controls.  Essentially, it allows you to navigate down from a parent element, locating children.  You can be a little recursive and then use the VisualTreeHelper on the child controls and dig deeper and deeper.

I've written a little helper that I've injected into the base class of all controls I'm writing for Silverlight and WPF.

/// <summary>
/// Navigates the control tree to find a child of a specific type.
/// </summary>
/// <param name="element">The parent element to search under.</param>
/// <param name="type">The type to search for.</param>
/// <returns>The first child of the specified type on success or null on failure.</returns>
protected object GetChildOfType(FrameworkElement element, Type type)
{
    int count = VisualTreeHelper.GetChildrenCount(element);
 
    for (int i = 0; i < count; i++)
    {
        FrameworkElement child = (FrameworkElement)VisualTreeHelper.GetChild(element, i);
 
        if (child != null)
        {
            if (child.GetType() == type)
                return child;
 
            object deeperChild = GetChildOfType(child, type);
 
            if (deeperChild != null)
                return deeperChild;
        }
    }
 
    return null;
}


Enjoy!

Thursday, June 23, 2011

Hello World

If I didn't start a blog without a Hello World post, then I wouldn't be a cliche programmer!