ColorGrid control is a fairly useful control for selecting
from a predefined list of colours. However, it can take up quite
a bit of screen real estate depending on how many colours it
contains. This article describes how you can host a
in a standard
ToolStrip control, providing access to both the
ColorGrid and the
ToolStrip control makes this surprisingly easy to
accomplish. First, we're going to need a component to host the
ColorGrid which we can ably achieve by inheriting from
ToolStripDropDown. So lets get started!
ToolStripDropDown class "represents a control that allows
the user to select a single item from a list that is displayed
when the user clicks a ToolStripDropDownButton" and is just
what we need to save use reinventing at least one wheel. This
class will essentially manage the interactions to the
ToolStripColorPickerDropDown is created we
automatically create a
ColorGrid control, set some default
properties and then add it to the
If we simply bound the
ColorChanged event of the
to select a colour, then you'd probably have great difficulty in
using the control properly - keyboard support is immediately out
of the question, and even some mouse support would be affected.
For this reason, I'm binding the
events to allow for a nicer editing experience. I'll also add a
Color property so that I can track color independently of the
ColorGrid, to enable cancel support.
In the key handler, I'm closing the drop down if either the
Enter or Escape keys are pressed. If it's
the former, we update our true
Color property. If the latter,
we don't. This way a user can cancel the drop down without
The mouse handling is fairly similar, with the exception we don't cover a cancel case. If the user clicks outside the bounds of the drop down it will be automatically closed.
Here we do a hit test, and if a colour was clicked, we close the drop down and update the internal colour.
Notice that I close the drop down before setting the colour. This is deliberate, as originally I had it the other way around (as would seem more logical). The problem with that is that change events will be raised for the modified colour - but the drop down palette is still visible on the screen which I found a hindrance while debugging.
I also noted that when the drop down opened, the
not have focus. That was easy enough to resolve by overriding
Now that the drop down is handled, we need a new
to interact with it.
For the actual button, I choose to inherit from
ToolStripSplitButton. This gives me two interactions, a drop
down, and a button. We will display the
ColorGrid via the drop
down, and the
ColorPickerDialog via the button, giving the
user both a simple and an advanced way of choosing a colour.
As with the
ToolStripColorPickerDropDown class, our new
ToolStripColorPickerSplitButton also has a dedicated colour
property. The reason for this is I don't want to create the drop
down component unless it's actually going to be used. After all,
why waste resources creating objects we're not going to need?
ToolStripSplitButton class calls
in order to set the
DropDown property if it doesn't have a
value. We'll override this to create our custom drop down.
In order to allow the developer to customise the
required, we need to expose the control so they can access it.
Browsable attribute prevents it from appearing in property
DesignerSerializationVisibility prevents the
property from being serialized.
Host property and the
make use of the private
EnsureDropDownIsCreated method, so
that the drop down is created on demand.
This means you can only customise the control from actual code
(such as from your forms
Load event, not by setting properties
on the designer.
As long as the
the existing designers will automatically detect it and allow
you to add them to your
(Although interestingly it seems to automatically remove the
There is a caveat however - the
ToolStripColorPickerSplitButton class must be
Originally I had it as
internal (as it is part of a
non-library project) but then it never showed up in designers.
If you display the drop down at design time, you'll find that you can continue to add items to the drop down underneath the hosted
ColorGrid. I couldn't find a way to disable this, unless I created a new designer myself.
DropDown property of a
been set, it will take care of the details of showing it, so
there's nothing more for us to do there. However, we do need to
add some code to display the
ColorPickerDialog if a user
clicks the main body of the button. This can be done by
Typically, buttons which display an editor for a colour also
display a preview of the active colour as a thick band
underneath the buttons icon. Although the
makes this a little harder than it should, we can add this to
ToolStripColorPickerSplitButton class by overriding the
The difficulty comes from the fact that the class doesn't give us access to its internal layout information, so we have to guess where the image is in order to draw our line. As there are quite a few display styles for these items, it can be a little tricky.
GetUnderlineRectangle method show above does a decent job
of guessing where the image should be and should work without
much in the way of tinkering.
If you are drawing a custom underline, you should make sure the bottom four pixels of your image are blank, as any details in these will be covered over by the image.
The full source code can be found in the demonstration program
for the ColorPicker controls on GitHub. Just add the
ToolStripColorPickerSplitButton.cs files to your project and
you should be good to go!
- 2015-02-28 - First published
- 2020-11-21 - Updated formatting
Like what you're reading? Perhaps you like to buy us a coffee?
- Hosting a ColorGrid control in a ToolStrip
- ColorPicker Controls 126.96.36.199 Update
- ColorPicker Controls Update 188.8.131.52
- ColorPicker Controls for Windows Forms