The main goal of ComponentOne ClearStyle™ technology is to allow developers to make simple visual appearance changes without having to deal with Microsoft Expression Blend, Styles and Templates. XAML is a very powerful and flexible markup language that allows us to do incredible things. But this incredible flexibility can sometimes lead to chaos because the cost of flexibility is complexity[1]. While complexity can sometimes be a good thing, complication is never. With that in mind, we came up with this new technology to help developers keep the complication out of their complex user interfaces. We have been developing custom XAML controls for over six years, so we know its capabilities and its limits. This document describes the pain points we have seen and how we are facing them to make your life easier. In the first section we will explain the general problem in a simple way. Then we will divulge the main points we wanted to solve and the set of rules or best practices we applied to our control design process. Later, we will describe the implementation details behind ClearStyle technology, as well as show a task-oriented comparison with and without ClearStyle.

The Problem

No matter whether you are working in WPF, Silverlight or any other XAML-based platforms, you likely have experienced the need to make a simple visual appearance change to a control. Say, for instance, that you wanted to change the color of a ScrollBar. Here is what happens if you change the Background property of the built-in Silverlight ScrollBar.

<ScrollBar Height="100" Width="20" />

<ScrollBar Height="100" Width="20" Background="DarkRed" />

There is no apparent change in visual appearance. On the other hand, the common Button control behaves differently to the same change.

<Button Content="MyButton" />

<Button Content="MyButton" Background="DarkRed" />

Notice a slight red color comes through on the Button. What’s happening to cause this is the Background property is applied only to the background element of the Button control. Every control is composed of multiple elements layered on top of one another. Think of a control containing multiple layers like the following diagram. A Button is a simple control with only a few layers. A ScrollBar is a bit more complex and the other elements on top of its background are too opaque for any color to shine through. Unfortunately, it’s not always practical to expose Brush properties for each element composing a control. Instead, you can customize the entire template of any control to get the desired look. That is why XAML platforms are considered extremely flexible. So if you truly want a vibrant, dark red ScrollBar it’s possible. Here is the official process.

  1. Open your project in Microsoft Expression Blend
  2. Edit a copy of the ScrollBar template (see Appendix)
  3. Dig through the different template parts until you find the parts that you need to change
  4. Apply changes to each state of the control so the look is consistent

The pain point is that working with over 600 lines of XAML just to change a background color becomes problematic from a maintenance standpoint. Just imagine the complexity when you need to apply this change to every control in your application that may include complex data grids and calendars. Instead of “spaghetti code” you now have “spaghetti XAML.” Maintaining a template for a standard control that Microsoft only updates every couple of years is one thing. For us at ComponentOne this is a bigger issue because we release updates for our controls three times a year. With each release we add features and functionality that users demand. These enhancements don’t break backward compatibility when it comes to programmatic API, however, every new bell and whistle requires changes to the template to define that bell or whistle’s appearance. Basically, changes to XAML templates are unavoidable in a custom control. So a solution to this problem was very important to ease the usability of our controls. The end result with ClearStyle technology makes everyone’s lives easier. Of course, you can also run away from the problem and just use default themes everywhere. But at that point you aren’t taking advantage of what XAML has to offer and you may as well stick to Windows Forms.

Principles and Goals

A lot of thought and consideration went into the implementation of ClearStyle. For each control we wanted to find the perfect balance between a crisp, clean public API and one that could be easily styled without having to get into control templates. That is not an easy task because each control part can have many appearance related attributes aside from just a background color. So we set the following three principles for appearance customization scenarios.

  • Simple changes should be simple
  • Detailed changes should be simple enough
  • The option for full redesign should always be available

Simple changes should be simple

We think small appearance changes should be done by anyone without the need of a tool. For example, the Background property should be honored by all controls in a smart way. ClearStyle innovation leverages this kind of simple change principle so you can quickly and easily style complex controls like our C1Scheduler.

<c1:C1Scheduler Background="DarkRed" Foreground="White" />

It might not be what everyone needs but it should be useful for someone. Not handling it is the worst thing we can do. In the current Silverlight framework the Background property is defined in Control, however not all controls actually support it. We’ll discuss more technically about how ClearStyle works in the last section.

Detailed changes should be simple enough

Since we develop a lot of complex controls that have a lot of working parts, we wanted to make sure that detailed changes to each part would be simple. Not all controls can be customized enough with just a Background brush. As mentioned before, it’s not practical to expose everything as properties to make them easily changeable. It sort of goes against the look-less principle of WPF and Silverlight, and it would also result in a very messy public API. Consider a property like MouseOverHeaderBorderBrush that changes the appearance of the header’s border when the mouse hovers over the control. In most common scenarios that property would not be worth having. We weighed the usefulness along with a bit of design knowledge and common sense to determine the appropriate properties to expose for each control. For example, our C1DataGrid control exposes the following Brushes:

  • AlternatingRowBackground
  • Background
  • BorderBrush
  • GroupingPanelBackground
  • HeaderBackground
  • HorizontalGridLinesBrush
  • MouseOverBrush
  • PressedBrush
  • RowBackground
  • SelectedBrush
  • ValidationBackground
  • VerticalGridLinesBrush

Plus, there are several Foreground properties that correspond to each background property where Text is involved. It’s not an abusive amount of properties but it’s enough to make detailed changes in a simple way. Other control states like MouseOver and Pressed are also considered in a very simple manner. The richness of brush properties gives you the ability to easily customize a style that has a wider color scheme.

<c1:C1DataGrid HeaderBackground="DarkRed" HeaderForeground="White"  
AlternatingRowBackground="LightGreen" SelectedBackground="Orange"  
GroupingPanelBackground="DarkBlue" GroupingPanelForeground="White"  
BorderBrush="Black" VerticalGridLinesBrush="Black" MouseOverBrush="GoldenRod">

That may not be the most beautiful color scheme imaginable but you get the idea. You are not limited to only using solid colors like the examples above. Any Brush property can contain a gradient or texture (ImageBrush/VisualBrush) to provide even more detailed customization.

The option for full redesign should always be available

Providing an easy alternative to generating templates and styles seems to be great, but there will always be some disadvantage and limitation. For example, exposing a Brush property for an object lets you easily change its color, however it does not handle setting a different pattern or shape for that object. Therefore, the option for full redesign should still be available for less common cases. That means everything should not only support ClearStyle and make simple things easier, but it should also be completely styleable through Expression Blend. We’ve made sure to keep all ComponentOne controls standardized so they also work completely like standard controls.

The Goals

With those principles in mind we came up with the following goals for our control libraries:

Be Graphics Designer-less

Developers should be able to easily tweak the control appearance without having to interact with templates and styles. This should be accomplished by just changing a few Brush properties. Also, the controls should look good when setting solid colors. Existing gradients in the control templates are honored and not wiped out by a solid color setting. Not all developers prefer to even create gradients.

Be Blend Friendly

This is actually a basic requirement, not introduced by ClearStyle. It’s good to highlight it here to reinforce our commitment. The templates and styles should be easily editable in Expression Blend. This means that not only should “Edit a Copy” of a control template be available, the templates should also show the actual control in design mode.

Expose Inner Styles

All object styles should be exposed as properties where possible. There is no need to copy the full template or style in order to change the style of an inner element. For example, if you just need to customize the style of the inner docking diamond of the C1DockControl control it does not require that you copy the control’s entire template.

Cascade appearance properties when logical

Some properties in some controls should propagate from the outer controls to the inner ones. For example, you don’t want to set the Background in the C1Menu control and then again in every C1MenuItem element. You just want to set it once and let inner controls adopt the same style.

Task-Oriented Comparison

Currently with all XAML controls, the way to theme it is to create a style resource template. In Microsoft Visual Studio alone this process is nearly impossible (without copying code from the internet), so Microsoft introduced the Expression Blend tool to make the task a bit easier. This introduces a challenge for developers who are not familiar with Blend and do not have the time to learn it, and having to jump back and forth between two tools is undesirable. You could hire a graphic designer but that adds to budget and communication costs. With ComponentOne ClearStyle™ technology the styling capabilities are brought to you in Visual Studio in the most intuitive manner possible. In most situations you just want to make simple styling changes so we believe the process should be as simple as you would expect. The differences in time and cost for both development and design time could be measured as follows. Task 1: Make your datagrid match a “Greeny” user interface

Consideration

Steps

Time Estimation

Cost Estimation

DataGrid without ClearStyle

  1. Buy Expression Blend
  2. Hire a graphic designer
  3. Make 4 control styles
  4. Change 3 resources.

3-5 hours creating theme + time spent making changes later

$500 + cost of graphic designer

C1DataGrid with ClearStyle

  1. Change 5 properties

3-5 minutes

(Studio for Silverlight or WPF)

Task 2: Give your end-user the ability to pick a color scheme for your datagrid

Consideration

Steps

Time Estimation

Cost Estimation

DataGrid without ClearStyle

  1. Buy Expression Blend
  2. Hire a graphic designer (or several)
  3. Make as many themes as you want the user to choose from

3-5 hours creating each theme + time spent adding more themes later once the user requests them

$500 + cost of graphic designer(s)

DataGrid with ClearStyle

  1. Write code to enable user to change a bunch of properties

1 hour

(Studio for Silverlight or WPF)

Task 1 shows a benefit of saving development time and cost. Task 2 shows that same benefit plus another benefit to having ClearStyle support. Some end-user applications give the user the option to change their theme. It’s a fun, fruitless feature that only adds enjoyment to the end-user. With ClearStyle the feature is very easy to implement as you are basically just setting a property at run-time while achieving an entire new look for a control.

Implementation Details

This section explains a how ClearStyle works. ClearStyle technology is implemented with two critical style tactics: property propagation and brush building.

Property Propagation

The idea of property propagation is quite simple. For example, if you change the background of a C1Menu control you would want this value to affect all of the inner C1MenuItem elements as well. Consider a menu with hundreds of items; you don’t want to repeat setting the same background value for all items. The property value should cascade inward. Cascading property values should be standard practice for all controls. Some controls do support it to some degree, but most do not. Our implementation of this uses binding. We use it very carefully, as we cannot override user values in both the property itself or in any style its set by.


/// <summary>  
/// Sets the binding if the dependency property has not been set  
/// previously and the style of the element don't set the property.  
/// </summary>  
/// <param name="target">The target.</param>  
/// <param name="dp">The dependency property.</param>  
/// <param name="source">The source.</param>  
/// <param name="sourcePropertyName">Name of the source property.</param>  
internal static void SetBinding(this FrameworkElement target, DependencyProperty dp, object source, string sourcePropertyName)  
{  
    var currentValue = target.ReadLocalValue(dp);  

    if (currentValue == DependencyProperty.UnsetValue &&  
        (target.Style == null || !target.Style.Contains(dp)))  
    {  
        // create binding if the property is available  
        target.SetBinding(dp, new Binding(sourcePropertyName)  
        {  
            Source = source  
        });  

        // Sometimes Setter.Property returns null  
        // and target.Style.Contains(dp) doesn't find it.  
        // After setting the binding Setter.Property works properly  
        // so we recheck.  
        // This caused a bug in that the first TabItem had  
        // bindings set when it shouldn't.  
        if (target.Style != null && target.Style.Contains(dp))  
        {  
            target.ClearValue(dp);  
        }  
    }  
    else if (currentValue is BindingExpression)  
    {  
        // re-set binding if the property was already bound by us  
        var exp = currentValue as BindingExpression;  
        if ((exp.DataItem == source)  
            && (exp.ParentBinding.Path.Path == sourcePropertyName))  
        {  
            target.SetBinding(dp, exp.ParentBinding);  
        }  
    }  
}  

Brush Building

For complex controls you usually have a primary color and then a series of very similar brushes that offer subtle variations of that color[2] (known as few hues, many values). Some of them may be vertical gradients, some horizontal gradients, etc. The desired behavior would be to change one color and have the other similar brushes update automatically. The solution would be to implement a “relative brush” that can take another brush as its source. Through ClearStyle we are able to create relative brushes. This can turn a simple color into a professional looking design easy enough for any developer to master. For example, notice when we set the ButtonBackground property of C1DatePicker the subtle, default gradient is preserved for the new color.

<c1:C1DatePicker Height="30" Width="120" />

<c1:C1DatePicker Height="30" Width="120" ButtonBackground="LightGreen" />

If you look closely you will notice the subtle gradient on the button is preserved. This relative brush is achieved using our own C1BrushBuilder class.

C1BrushBuilder

The C1BrushBuildder is an element present in most of the ComponentOne control templates that has the ability to convert one brush into another while preserving the gradient of the first one. Consider the following diagram. DesignBrush and DesignColor are specified by the designer whereas Input is typically bound to a property of the control through a template binding. When the property bound to the Input is changed a new resulting brush is created and available through the Output property.


<c1:C1BrushBuilder x:Name="BackgroundBrush"  
Input="{TemplateBinding Background}"  
DesignBrush="{StaticResource MyDesignBrush}"  
DesignColor="{StaticResource MyDesignColor}"/>  

The brush in the output property is consumed by at least one visual element through a binding using the name of the brush builder.


<Border Background="{Binding ElementName=BackgroundBrush, Path=Output}" />  

This way the border background reflects a brush which was converted by the C1BrushBuilder considering both the original element’s gradient and the brush set in a public property of the control. There is an alternative implementation to C1BrushBuilder that uses transparencies. You lay down a solid color in the back and then lay a semi-transparent gradient element on top. The result is OK but it has a few cons:

  • Doesn’t handle dark colors well because the top element is always lighter than the back color
  • Doesn’t handle transparency right as the top element is on top of the transparent color

Conclusion

ClearStyle technology is a unique feature found in all ComponentOne Silverlight, WPF, and other XAML controls (such as Windows Phone and WinRT XAML). No matter whether you’re a developer or even a designer, you can benefit from using ComponentOne controls.

  • Style controls without the need for Expression Blend, or if you still decide to use Blend then styling the controls is still easier than other 3rd party controls and even standard ones.
  • Styling is simple and intuitive. It’s not difficult to set several Brush properties on a control, in fact it’s second nature if you are familiar with Visual Studio. You can even create a style resource that applies these simple Brush properties to all instances of a control for even more efficient designing.
  • Detailed changes are possible and easy because complex controls have more available brushes in addition to the usual Background and Foreground properties. In most standard controls these are the only two brushes you can set and they will not handle all states and parts of the control in all cases.
  • The option for full re-design is still there as ClearStyle doesn’t interfere with the standard approach of modifying control templates. ClearStyle is intended to be a quick solution to simple, common design needs.

For more information including a video demonstration, visit the ComponentOne website: http://www.componentone.com/clearstyle/


[2] http://designinginterfaces.com/firstedition/index.php?page=Few\_Hues\_Many_Values [1] http://blog.fedecarg.com/2009/02/22/zend-framework-the-cost-of-flexibility-is-complexity/