This tutorial demonstrates how to create a color picker using nothing more than few elements and Telerik's slider control for Silverlight.
To start off, create a new Silverlight project. It is up to you to decide whether you want a web page in the project or not. This particular example does not to include a web page, but a simple html page that is generated dynamically. Once you have the project created go ahead and add a reference to the Telerik.Windows.Controls.dll. At the top of your main UserControl, add a namespace in order to use the dll. Check if everything compiles and we are done with the preparation.
On the image bellow you can see what the basic structure of the color picker will be.
As you can see there are 3 sliders (hue, saturation and luminance), 1 thumb to pick the color, 1 element to display the result(can be anything that you wish, but in this particular example it is a Rectangle) and a Pad(a Grid that contains the thumb).
You might have already guessed but we are going to use the HSL(hue,saturation,luminance) to RGB(red,green,blue) conversion. Since this is not a tutorial on how the conversion exactly works I advice you to search for HSL/HSV to RGB in case you want to understand the details.
This is the structure of the elements in Blend. Most of the elements have already been explained. One key part that needs some explanation is the resizer element.
The resizer is necessary in order to be able to move the color picker thumb. Basically, moving the color picker thumb causes the saturation and luminance sliders to update their values. These values are set as width and height respectively to the resizer. Changing resizer's size will force the container grid(pad) to recalculate the size of its row and columns and thus causing the thumb to move. Simple enough!
1: private void LuminanceSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
3: resizer.Height = DistanceConverter.ValueToPixels((double)e.NewValue, (pad.ActualHeight - colorPickerThumb.ActualHeight), (luminanceSlider.Maximum - luminanceSlider.Minimum));
6: private void SaturationSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
8: resizer.Width = DistanceConverter.ValueToPixels((double)e.NewValue, (pad.ActualWidth - colorPickerThumb.ActualWidth), (saturationSlider.Maximum - saturationSlider.Minimum));
Note: The ValueToPixels method accepts 3 arguments - the current value of the slider, the size in pixels of the container that holds the color picker thumb, the range of the slider(Range == Maximum - Minimum)
Change the value of the slider's and see how this reflects the thumb. Download source
On the sample above, if you try to move the thumb nothing will happen. This is in fact the next step - making the thumb dragable.
Thumb control has 2 major events - DragStarted and DragDelta. Our goal is:
1. On DragStarted to obtain the value of saturation and luminance slider's.
2. On DragDelta to calculate the offset(horizontal and vertical) and convert it from pixels to value .
3. Assign the converted values to saturation and luminance sliders.
4. Optional: Make saturation and luminance sliders invisible
1: // ColorPicker Thumb Drag events
2: private void ColorPickerThumb_DragStarted(object sender, System.Windows.Controls.Primitives.DragStartedEventArgs e)
4: this.dragDeltaX = saturationSlider.Value;
5: this.dragDeltaY = luminanceSlider.Value;
8: private void ColorPickerThumb_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
10: double offsetX = 0;
11: double offsetY = 0;
13: offsetX = DistanceConverter.PixelsToValue(e.HorizontalChange, (pad.ActualWidth - colorPickerThumb.ActualWidth), (saturationSlider.Maximum - saturationSlider.Minimum));
14: offsetY = DistanceConverter.PixelsToValue(e.VerticalChange, (pad.ActualHeight - colorPickerThumb.ActualHeight), (luminanceSlider.Maximum - luminanceSlider.Minimum));
16: this.dragDeltaX += offsetX;
17: this.dragDeltaY += -offsetY;
19: saturationSlider.Value = this.dragDeltaX;
20: luminanceSlider.Value = this.dragDeltaY;
Since we have the two slider's done, it is time do create the third component - the hue slider.
This is an example of a hue slider from Expression Blend.
The hue slider has a little bit different responsibility that the saturation and luminance sliders. Besides updating the result box, the hue sliders takes care of updating the gradient background of the pad as well.
Like the other two sliders, the value of the hue slider is used to convert from HSL to RGB. The interesting task here is to make the slider to look like the one on the last image. This means that we have to restyle the slider completely(track, thumb etc).
Since we have all the necessary parts to assemble a decent color picker, I'd like to spend just a little bit of time on the converter class that does the magic - ColorConverter.cs (included in the source). ColorConverter has one very important method called HSLtoRGB. Correct, this method takes 3 values - hue, saturation and luminance and return an object of type Color.
This is the final result. Dragging the thumb and changing the value of the hue slider makes the result box change its color. Enjoy!
Valentin Stoychev (@ValioStoychev) for long has been part of Telerik and worked on almost every UI suite that came out of Telerik. Valio now works as a Product Manager and strives to make every customer a successful customer.