ComponentOne ClearStyle technology is one of the most unique and useful features of Studio for Silverlight and WPF. ClearStyle makes styling controls very easy. It allows developers to customize a control's appearance (ie colors) without having to hassle with XAML templates and Expression Blend. You can fully customize the style of any ComponentOne control right on the Visual Studio 2010 design surface thanks to ClearStyle. And the best thing is that ClearStyle is baked into the C1 controls, so there's nothing new you have to learn. This blog post explains how you can take advantage of ClearStyle and save time styling your applications.

ClearStyle works like this:

  1. Each ComponentOne control exposes brush properties for each key part. For example, C1Scheduler has brushes for AppointmentForeground, SelectedBackground, TodayBackground, etc.
  2. You, the developer, can easily set these brushes in Visual Studio 2010 using the rich brush editor. Create solid color brushes, gradient brushes or image brushes. All will work with ClearStyle.
  3. Since each control part is composed of multiple layers, the brushes you apply are distributed throughout the layers. This magical process is ClearStyle technology! Question: Have you ever tried to set the Background brush for a Button or any standard control and noticed that the colors don't distribute through the control's layers? Yea, that's a prime example of why ClearStyle is so useful to have baked into your controls.

(Optional) Encapsulate these brush property settings as Styles just as you would for any control. The short and simple styles you create can be used across your entire application. See the end of this blog post for an example.

The objective with ClearStyle is that simple appearance changes should be simple to accomplish. Developers should be able to easily tweak the control appearance without having to interact with templates and styles. Of course, you're still free to fully customize the control templates to get the exact style needed, should more precision be required.

Saving Time: A Task-Oriented Comparison

ClearStyle not only makes styling simple, it also saves a lot of time. Without ClearStyle you have two options:

  1. Customize a control's template (XAML) to get the colors you want.
  2. Stick with default style.

Obviously #2 is the easiest option (for you lazy folks), but let's see just how much work is involved in #1 and how ClearStyle saves us time.

Customizing the Microsoft DataGrid Selected Row Color

For example, let's take on the common task of changing the Microsoft's DataGrid's selected row color. The sdk DataGrid control includes a few brushes: Background, RowBackGround and AlternatingBackground. But none of these brushes apply to the selected row. To change extra appearance aspects of the DataGrid we must edit a copy of the control's template. In Expression Blend, right-click the DataGrid control and select Edit Additional Templates | Edit Row Style | Edit a Copy...

Then Blend asks how you want to declare your style, implicitly or explicitly (Explicit styles are given a key and only control instances which refer to the key will get that style. Implicit styles apply to all instances of a control type within its scope, and therefore do not need a Key). Choose "Apply to all" to create an implicit style.

Next, choose "Application" under Define in. This means the style's scope will apply to the entire application. Click OK. Expression Blend spits out a bunch of XAML into the App.xaml file:


<Style TargetType="sdk:DataGridRow">  
    <Setter Property="IsTabStop" Value="False" />  
    <Setter Property="Template">  
        <Setter.Value>  
            <ControlTemplate TargetType="sdk:DataGridRow">  
                <sdk:DataGridFrozenGrid x:Name="Root">  

                    <sdk:DataGridFrozenGrid.Resources>  
                        <Storyboard x:Key="DetailsVisibleTransition">  
                            <DoubleAnimation Storyboard.TargetName="DetailsPresenter" Storyboard.TargetProperty="ContentHeight" Duration="00:00:0.1" />  
                        </Storyboard>  
                    </sdk:DataGridFrozenGrid.Resources>  

                    <VisualStateManager.VisualStateGroups>  
                        <VisualStateGroup x:Name="CommonStates">  
                            <VisualState x:Name="Normal"/>  
                            <VisualState x:Name="NormalAlternatingRow">  
                                <Storyboard>  
                                    <DoubleAnimation Storyboard.TargetName="BackgroundRectangle" Storyboard.TargetProperty="Opacity" Duration="0" To="0"/>  
                                </Storyboard>  
                            </VisualState>  
                            <VisualState x:Name="MouseOver">  
                                <Storyboard>  
                                    <DoubleAnimation Storyboard.TargetName="BackgroundRectangle" Storyboard.TargetProperty="Opacity" Duration="0" To=".5"/>  
                                </Storyboard>  
                            </VisualState>  
                            <VisualState x:Name="NormalSelected">  
                                <Storyboard>  
                                    <DoubleAnimation Storyboard.TargetName="BackgroundRectangle" Storyboard.TargetProperty="Opacity" Duration="0" To="1"/>  
                                </Storyboard>  
                            </VisualState>  
                            <VisualState x:Name="MouseOverSelected">  
                                <Storyboard>  
                                    <DoubleAnimation Storyboard.TargetName="BackgroundRectangle" Storyboard.TargetProperty="Opacity" Duration="0" To="1"/>  
                                </Storyboard>  
                            </VisualState>  
                            <VisualState x:Name="UnfocusedSelected">  
                                <Storyboard>  
                                    <DoubleAnimation Storyboard.TargetName="BackgroundRectangle" Storyboard.TargetProperty="Opacity" Duration="0" To="1"/>  
                                    <ColorAnimation Duration="0" Storyboard.TargetName="BackgroundRectangle" Storyboard.TargetProperty="(Fill).Color" To="#FFE1E7EC"/>  
                                </Storyboard>  
                            </VisualState>  
                        </VisualStateGroup>  
                        <VisualStateGroup x:Name="ValidationStates">  
                            <VisualState x:Name="Valid"/>  
                            <VisualState x:Name="Invalid">  
                                <Storyboard>  
                                    <ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetName="BackgroundRectangle" Storyboard.TargetProperty="Visibility">  
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>  
                                    </ObjectAnimationUsingKeyFrames>  
                                    <DoubleAnimation Storyboard.TargetName="InvalidVisualElement" Storyboard.TargetProperty="Opacity" Duration="0" To="1"/>  
                                </Storyboard>  
                            </VisualState>  
                        </VisualStateGroup>  
                    </VisualStateManager.VisualStateGroups>  
                    <sdk:DataGridFrozenGrid.RowDefinitions>  
                        <RowDefinition/>  
                        <RowDefinition Height="Auto"/>  
                        <RowDefinition Height="Auto"/>  
                    </sdk:DataGridFrozenGrid.RowDefinitions>  
                    <sdk:DataGridFrozenGrid.ColumnDefinitions>  
                        <ColumnDefinition Width="Auto" />  
                        <ColumnDefinition/>  
                    </sdk:DataGridFrozenGrid.ColumnDefinitions>  

                    <Rectangle x:Name="BackgroundRectangle" Grid.RowSpan="2" Grid.ColumnSpan="2" Opacity="0" Fill="Orange"/>  
                    <Rectangle x:Name="InvalidVisualElement" Grid.RowSpan="2" Grid.ColumnSpan="2" Opacity="0" Fill="#FFF7D8DB"/>  

                    <sdk:DataGridRowHeader Grid.RowSpan="3" x:Name="RowHeader" sdk:DataGridFrozenGrid.IsFrozen="True" />  
                    <sdk:DataGridCellsPresenter Grid.Column="1" x:Name="CellsPresenter" sdk:DataGridFrozenGrid.IsFrozen="True" />  
                    <sdk:DataGridDetailsPresenter Grid.Row="1" Grid.Column="1" x:Name="DetailsPresenter" />  
                    <Rectangle Grid.Row="2" Grid.Column="1" x:Name="BottomGridLine" HorizontalAlignment="Stretch" Height="1" />  
                </sdk:DataGridFrozenGrid>  
            </ControlTemplate>  
        </Setter.Value>  
    </Setter>  
</Style>  

That's a lot of XAML I really don't have time to deal with. But after some tinkering I discovered that the Rectangle element on line 66 visually represents the selected row. By changing the Fill on this rectangle to Orange the selected row color is now modified. Also note that this chunk of XAML is just for the RowStyle of the DataGrid. There's also the CellStyle, ColumnHeaderStyle, RowHeaderStyle, DragIndicatorStyle and a few more. If you had to modify all of these you are looking at over 400 lines of XAML you have to learn and mess with! And then you and your team have to maintain this too...

Customizing the C1DataGrid Selected Row Color (with ClearStyle baked in)

With ComponentOne ClearStyle and C1DataGrid here are the steps to change the selected row color.

  1. You can work right in Visual Studio 2010 (no need for Expression Blend!)
  2. Select the C1DataGrid and set the SelectedBrush to Orange
  3. Go reward yourself for the extra time you just saved!

If you want to have this selected brush apply to ALL C1DataGrid's then you need to create a style resource, just as you would for any control. This promotes organizing your styles in one place in your application. The style could look like this, for example:


<Style TargetType="c1:C1DataGrid">  
    <Setter Property="SelectedBrush" Value="Orange" />  
</Style>  

Keep in mind even with ClearStyle you don't necessarily have to fire that graphic designer you hired because you didn't want to learn Expression Blend. You'll need to keep him/her around to help style all of your non-ComponentOne controls.