Building a Silverlight Color Picker Control - Part 2

This is a multi-part series on building a Silverlight Color Picker Control, please check out the Introduction if you missed it!

Before we write any actual code, it's nice to have some visuals to use as a reference.  There are many ways to represent color spaces.  One of the most common color space representations allows the user to pick a hue and then pick a saturation/luminosity combination.  The diagram below is a simplified view of this layout.  From this diagram, we can infer the XAML primitives that will be necessary to present our control.

Color Picker Diagram

Hue Selector

The Hue Selector is really a gradient that traverses each color extreme.  Do you remember your primary colors?

Red Yellow Green Blue Cyan Magenta Red (Again)
#ff0000 #ffff00 #00ff00 #0000ff #00ffff #ff00ff #ff0000
0 0.17 0.33 0.50 0.66 0.83 1

As it turns out, this is easy to represent in XAML.  Simply create a <Rectangle> primitive and use the the Linear Gradient to fill the rectangle.

   1:  <Rectangle Canvas.Left="0" Canvas.Top="0" Width="20" Height="180" > 
   2:    <Rectangle.Fill> 
   3:      <LinearGradientBrush StartPoint ="0,0" EndPoint="0,1"> 
   4:        <GradientStop Offset="0.00" Color="#ffff0000"/> 
   5:        <GradientStop Offset="0.17" Color="#ffffff00"/> 
   6:        <GradientStop Offset="0.33" Color="#ff00ff00"/> 
   7:        <GradientStop Offset="0.50" Color="#ff00ffff"/> 
   8:        <GradientStop Offset="0.66" Color="#ff0000ff"/> 
   9:        <GradientStop Offset="0.83" Color="#ffff00ff"/> 
  10:        <GradientStop Offset="1.00" Color="#ffff0000"/> 
  11:      </LinearGradientBrush> 
  12:    </Rectangle.Fill> 
  13:  </Rectangle>

 

Saturation / Brightness Selector

The Saturation / Brightness Selector is really two orthogonal gradients on top of the selected hue.  The saturation gradient starts out as White an becomes 100% transparent as you move from left to right.  The brightness gradient starts out as black and becomes 100% transparent as you move from bottom to top. Creating these gradients and stacking them produces the desired effect.

   1:  <Rectangle x:Name="rectSample" Width="180" Height="180"></Rectangle> 
   2:  <Rectangle x:Name="rectWhiteGradient" Width="180" Height="180"> 
   3:    <Rectangle.Fill> 
   4:      <LinearGradientBrush StartPoint="0,0" EndPoint="1,0"> 
   5:        <GradientStop Offset="0" Color="#ffffffff"/> 
   6:        <GradientStop Offset="1" Color="#00ffffff"/> 
   7:      </LinearGradientBrush> 
   8:    </Rectangle.Fill> 
   9:  </Rectangle> 
  10:  <Rectangle x:Name="rectBlackGradient" Width="180" Height="180"> 
  11:    <Rectangle.Fill> 
  12:      <LinearGradientBrush StartPoint="0,1" EndPoint="0, 0"> 
  13:        <GradientStop Offset="0" Color="#ff000000"/> 
  14:        <GradientStop Offset="1" Color="#00000000"/> 
  15:      </LinearGradientBrush> 
  16:    </Rectangle.Fill> 
  17:  </Rectangle>

 

Hex Code and Selected Color

These are the easiest of all.  Simply create two rectangles and position them.

   1:  <Canvas Canvas.Top="180" Canvas.Left="0"> 
   2:    <Rectangle x:Name="SelectedColor" Width="200" Height="20" Fill="Black" /> 
   3:    <Rectangle Width="60" Height="20" Fill="Black" /> 
   4:    <TextBlock x:Name="HexValue" Foreground="White" Width="100" Text="#FF0000" 
FontFamily="Arial" FontSize="11" Canvas.Top="4" Canvas.Left="5"  Height="10" /> 
   5:  </Canvas>

 

Cursors

There are two cursors that I've left of the diagram above.  One cursor represents the selected hue and the other represents the selected saturation/brightness combination.  I used Expression Design to create the hue selector cursor since it is created with a polygon.  The saturation/brightness cursor could be built without any additional tool support.

   1:  <Canvas x:Name="SampleSelector" Width="10" Height="10" Canvas.Left="100" Canvas.Top="96"> 
   2:    <Ellipse Width="10" Height="10" StrokeThickness="3" Stroke="#FFFFFFFF"/> 
   3:    <Ellipse Width="10" Height="10" StrokeThickness="1" Stroke="#FF000000"/> 
   4:  </Canvas>
   5:   
   6:  <Canvas x:Name="HueSelector" Height="8" Canvas.Left="0" Canvas.Top="-4"> 
   7:    <Path Width="5" Height="8" Stretch="Fill" StrokeLineJoin="Round" Stroke="#FF000000" 
Fill="#FF000000" Data="F1 M 276.761,316L 262.619,307.835L 262.619,324.165L 276.761,316 Z " /> 
   8:    <Path Width="5" Height="8" Canvas.Top="8" Canvas.Left="20" Stretch="Fill" StrokeLineJoin="Round" 
Stroke="#FF000000" Fill="#FF000000" 
Data="F1 M 276.761,316L 262.619,307.835L 262.619,324.165L 276.761,316 Z "> 
   9:      <Path.RenderTransform> 
  10:        <RotateTransform Angle="180" /> 
  11:      </Path.RenderTransform> 
  12:    </Path> 
  13:  </Canvas>

The End Result

Each of these pieces combine to produce something like the figure below.  Of course, this is pretty much useless until we wire up the XAML primitives.

 Color Picker

Conclusion

Hopefully this post gives you a little insight into how the UI was composed.  Next time, we will finish off the UI and begin writing actual code.  See you then!

Comments have been closed on this topic.