Pickers Library is a .NET Windows Control Library that aids in creating Picker-style controls.
What is a 'Picker' Control?
A 'picker' control can be thought of as a control, which allows you to select a value from rich, drop-down UI instead of a plain list. For example, we have the
DateTimePicker control. Similarly, the color selector in Microsoft® Word is an example of a picker.
The .NET Windows Forms
PropertyGrid control uses many different kinds of rich drop-downs for presenting value options for a property. For example:
The interface for choosing the date and time is common and available to us outside the
DateTimePicker control (as mentioned earlier). But what if we want some other interface out of the
The ColorPicker Article
Palo Mraz gives a magical answer to the above question in his ColorPicker and ColorPicker Revisited articles. He describes how to emulate the behavior of the
PropertyGrid by leveraging the Windows Forms design-time infrastructure to host the color-choosing interface inside a normal control. Please read the original ColorPicker article before proceeding. The technique discussed by Palo Mraz can be applied to host any other
UITypeEditor inside our control. The code for invoking the drop-down selection UI out of the
UITypeEditor is more or less the same for every
Custom-built Drop-down UIs
Sometimes, we may not find a cool drop-down UI for a specific type of value in the
PropertyGrid. In such a case, we can build our own UI and display it without using a
Palo Mraz discussed the right method for keep the drop-down UI "holder" form on screen, and his
ColorPicker implementation contains the code for positioning the drop-down holder on the screen correctly. This code can also be used to display a custom-built UI.
I have generalized this code using generics. The code for managing the appearance and behavior of the control has been put at one place. So, to create a picker we only need to create a drop-down ourself or find a
UITypeEditor that provides one for us.
Inside the Code
IDropDownUI & ISyncDropDownUI Interface
These interfaces defines the basic methods that are used by
PickerBase class to display the drop-down and retrieve the selected value from it. The
ISyncDropDownUI interface adds the
UpdatePicker event to update the value in the picker control without having to control the display.
public abstract class PickerBase<T, U>
: Control where U : Control, IDropDownUI, new()
This is the ultimate base class for a picker control.
T specifies the .NET Type for picker's value (the selection from the drop-down UI).
U specifies the .NET Type of the Control that presents the drop-down selection UI. It must implement the
IDropDownUI interface, which requires it to implement the methods
SetSeletedValue, so that the picker can drop-down the UI with correct defaults. It also implements the event
CloseDropDown, which is a signal that the user has selected the value and drop-down must be closed. Optionally it can also implement the
ISyncDropDownUI interface to add the
Storing the Selected Value
A private member of type
_value, stores picker's value. It is accessed programmatically through the
Value property. The
SetValueCore method does the task of storing the value and setting the control behavior and display according to the value. When this value changes either by user selection or programmatically, the
ValueChanged event is raised. There is an
abstract GetDefaultValue method, which must be overridden to provide a dynamic default value for the control for proper design time behavior.
The appearance of the picker is managed using the Adapter model, as done by Palo Mraz in ColorPicker Revisited. The
IPickerDisplayAdapter interface is used to create a display adapter that provides any
Control as the appearance for the picker. It interacts with the display control and tells the picker when to display drop-down using the
DropDown event. It also allows the picker to do some custom rendering using the
DrawIcon events. The picker displays this control with dock set to
DockStyle.Full. An abstract base class called
PickerDisplayAdapter has been provided to allow easy implementation. Two read-made adapters
EditableComboBox appearances) and
CheckButton appearance) are provided by default. For more information, see the source code.
NOTE: The code for
EditableComboBox appearance is mainly Palo Mraz's implementation, with a little fibbing to keep up with my "generic implementation".
Displaying the Drop-down
A protected member
DropDownHolder is a reference to the form window that hosts the drop-down UI. It is of type
DropDownForm, which is a
Form designed for hosting the custom-built drop-down UI or the UI provided by a
UITypeEditor. (Both are in the form of a control.) When the display adapter raises the
DropDown event, the picker calls the
ShowDropDown method, which creates an instance of the drop-down UI control (
U), calls a virtual method
InitializeDropDownControl(U control) to let subclasses perform custom initialization, and shows it on screen using
DoDropDown method. When the user selects a value, the drop-down UI raises the
CloseDropDown event, and the picker forces the
DropDownHolder to be closed down. If the user cancels the selection, the
DropDownHolder closes itself and tells the picker that the selection was cancelled.
public abstract class SvcPickerBase<T, E>
: PickerBase<T, SvcPickerBaseUI> where E : UITypeEditor, new()
SvcPickerBase class is used to host the selection UIs from
UITypeEditors. Just specify the .NET type of the
UITypeEditor descendant in the
E type parameter and see the magic!
SvcPickerBase no longer needs a custom built UI, this functionality is hidden using a dummy
private class PickerEditorService<ST, SE>
: IWindowsFormsEditorService, IServiceProvider where SE :
This class provides the service for hosting the
SvcPickerBase, by implementing the
IWindowsFormsEditorService interface and
IServiceProvider interface. The
valueEditorService private member in
SvcPickerBase holds an instance of this class, so that it can be used for displaying the drop-down. For details, see Palo Mraz's ColorPicker.
ShowDropDown() in SvcPickerBase
This is a carry over from Palo Mraz's
ColorPicker code. It overrides the process of displaying a custom-build UI and replaces it with the method of displaying the UI provided by
UITypeEditor. It calls the
EditValue of the
UITypeEditor descendant passing it an instance of the
PickerEditorService class (
valueEditorService) and the current value. The method uses the instance to display drop-down selection UI. When the user selects a value, it signals
PickerEditorService to close the drop-down, which in turn asks the picker to close the drop-down form. If the selection is cancelled, the
DropDownHolder closes itself, and tells
PickerEditorService object (and thus the picker) that the selection was cancelled.
Using the Code
Using the PickerBase Class
PickerBase class can be used to create a picker control with minimum amount of code. Just follow the following steps:
- Create a control that serves as the drop-down UI. It is better to design it such that the user can select the value with a single-click
- Add implementation declaration for the
IDropDownUI interface to your drop-down UI control class
- Add a
RaiseCloseDropDown() method and selected value member, for your ease:
private TypeName selectedValue;
private void RaiseCloseDropDown()
if (CloseDropDownHolder != null)
- Implement the
GetSelectedValue() and the
void IDropDownUI.SetSelectedValue(object value)
selectedValue = (TypeName)value;
- Make sure that your UI updates the
selectedValue variable as the user selection changes and call
RaiseCloseDropDown() at the right time.
Note: Please see the example
- Create the main picker control class by extending the
PickerBase class. As
PickerBase is a generic class, give the types of picker's value and your UI control to it as type parameters and see the magic. For example, you want to create a picker for values of type
TypeName and your UI is called
public class TypeNamePicker : PickerBase<TypeName, TypeNameUI>
protected override TypeName GetDefaultValue()
Note: You must override the
GetDefaultValue method, without it your code won't compile and your picker control will not behave properly in the designer. If you want to add additional functionality, you can override other methods (see source code for more information).
- If you implement the
ISyncDropDownUI interface, then you need to add the
UpdatePicker event to your implementation. The picker uses this event to update its value with closing your control first. So you can raise this event when the selection in your control changes.
SvcPickerBase is much easier, as it aids you in using a UI from the
PropertyGrid. Figure out the class name of the type editor of the Type of the value you want the picker for. Then just inherit
SvcPickerBase as shown below:
Suppose you want to create a picker for values of type
TypeName and the
UITypeEditor descendant, you're using to provide drop-down UI is called
public class TypeNamePicker : SvcPickerBase<TypeName, TypeNameEditor>
protected override int HeightCorrection
protected override TypeName GetDefaultValue()
protected override string FormatValue(TypeName value)
Points of Interest
Some example pickers have been provided. Please do see them.
Please report any bugs, errors, suggestions about code/article, new features here at the article at CodeProject.
- v 188.8.131.52 (Oct 15, 2007) - Implemented the
EditableComboBoxDisplay class. Added the
ISyncDropDownUI interface (to add the
UpdatePicker feature). Added the
ValueFromString methods to the
PickerBase class. Updated the article to reflect all these changes.
- v 184.108.40.206 - Rewrote the article to be more descriptive. Added display adapter support, which adds the combo-box, editable combo-box and check-box button look. (This required more refactoring that coding.)
- v 220.127.116.11 - First version (with basic support for creating pickers and no adapter model, only combobox look)