Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

WPF ColorPicker and BrushEditor

0.00/5 (No votes)
26 Jun 2012 1  
Similar to KAXAML's.

Introduction 

Well, I still hadn't found the perfect WPF ColorPicker Control to use in my projects. There are some nice ones out there, but my favourite is KAXAML's, so, I thought I might try to replicate it.  

Background  

The project is loosely MVVM and contains two UserControls, ColorEditor and BrushEditor and are packaged in a separate class library project for your convenience.  

The first hurdle I had was trying to generate the ColorPicker swatch. WriteableBitmap was terribly slow, so I decided to cache the 100 Hue swatches (being 0 - 1 with increments of 1%). Generating the Bitmaps was made much easier (having never had an occasion to use them) with the SimpleBitmap class found in the Community Content section of WriteableBitmap (http://msdn.microsoft.com/en-us/library/system.windows.media.imaging.writeablebitmap.aspx)  

The next hurdle for me was retemplating the Sliders for Hue and Alpha, again, something I hadn't done before. I mucked about with a couple of ControlTemplates before taking KAXAML's own Simple Styles style and bending it to my will. The Hue Slider background is simply a Border with a LinearGradientBrush and 7 GradientStops.  

The Alpha Slider and selected color box were somewhat tricky too, and I must profess to not fully understanding why the DrawingBrush that displays the checker pattern works.  

However, I think the trickiest part of this, to my surprise, was actually the RGBA/HSLA TextBox's! Basically, the problem is this. If you update say, the R value, you must also update H, S and L. If you update H, you must update R, if you update S, you must update R. This mightn't be so bad except that the conversion code from RGB to HSL isn't perfect. Ie, HSL (0.56, .60, .23) might not align perfectly to an RGB value.  So, it rounds the RGB value. But perhaps that rounding alters the H value just a tiny bit. So we alter the RGB values, which skew the H just a tiny bit. In the end, I simply said, if you change the H value, set a flag, update the RGB values, when they attempt to update the HSL values, check if that flag is set. If so, don't update. Simple in retrospect of course. 

Using the code   

The editors are used just like any other UserControl.

<Window 
    x:Class="BrushEditor.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:ColorEditor="clr-namespace:Lovatts.ColorEditor;assembly=Lovatts.ColorEditor" 
    Title="MainWindow" 
    Height="350" 
    Width="525">

  <ColorEditor:BrushEditor></ColorEditor:BrushEditor>
</Window>

But you can also bind to/use the underlying ViewModels: 

ColorEditor colorEditor = new ColorEditor();
colorEditor.ColorEditorViewModel.Color = Colors.Blue;
colorEditor.ColorEditorViewModel.RGB.A = 67;
Lovatts.ColorEditor.BrushEditor brushEditor = new Lovatts.ColorEditor.BrushEditor();
brushEditor.BrushEditorViewModel.BrushType = BrushTypes.Radial;
brushEditor.BrushEditorViewModel.Center = new Point(1, 0);
brushEditor.BrushEditorViewModel.GradientStops.Clear();   
brushEditor.BrushEditorViewModel.GradientStops.Add(new GradientStopViewModel(Colors.Blue, 1);  
brushEditor.BrushEditorViewModel.GradientStops.Add(new GradientStopViewModel(Colors.Red, 0));

Brush serialization/deserialization methods are included for convenience. 

string xml = brushEditor.BrushEditorViewModel.SerializeBrushToXml();
brushEditor.BrushEditorViewModel.DeserializeBrushFromXml(xml);

The XML output being...

<RadialGradientBrush
  Center="1,0" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
  <RadialGradientBrush.GradientStops>   
    <GradientStop
      Color="#FFFF0000"
      Offset="0" />
    <GradientStop
      Color="#FF0000FF"
      Offset="1" />
  </RadialGradientBrush.GradientStops>
</RadialGradientBrush>

Points of Interest

Well.. this is my first ever CodeProject submission and took about a day to write. 

There's a slight issue when changing the hue slider, in that it will sometimes snap the palette thumb to an RGB value.  

The hex code TextBox is automatically set to OverType (using the method below) which I find much more user friendly:  

private void MakeHexTextBoxOverType()
{
    PropertyInfo textEditorProperty = typeof (TextBox).GetProperty(
       "TextEditor", BindingFlags.NonPublic | BindingFlags.Instance);
    object textEditor = textEditorProperty.GetValue(hexTextBox, null);
    // set _OvertypeMode on the TextEditor
    PropertyInfo overtypeModeProperty = textEditor.GetType().GetProperty(
       "_OvertypeMode", BindingFlags.NonPublic | BindingFlags.Instance);
    overtypeModeProperty.SetValue(textEditor, true, null);
} 

History 

  • 19/6/2012: Posted article.
  • 20/6/2012: Uploaded source 
  • 26/6/2012: Updated Background 

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here