If you create a WinForms application and wish to allow your users to select many enum values from all enum values, you can use EnumFlagsSelector
.
is custom WinForms control that simplifies the creation of user interfaces based on enum types. It makes it easy to choose many enum values from the values of the enum type.EnumFlagsSelector
How To Select Many Enum Values With EnumFlagsSelector?
In the article Select one enum value with EnumSelector, we have discussed how to create the WinForms custom control EnumSelector
to allow the user to select one enum value from the values of the enum type. Although one can use several EnumSelector
instances to achieve this goal, a better solution is to use EnumFlagsSelector
.
EnumFlagsSelector
is a listbox that displays each value of the enum type (decorated with Flags Attribute) with a checkmark next to it. The user can independently check or uncheck each enum value. When the user checks the value,the value is included in the selection. When the user unchecks the value, The value is excluded from the selection.
To use this custom WinForms control, You should inherit from EnumFlagsSelector
with enum type. The enum type should be decorated with Flags attribute.
The Selected
property holds the currently selected values. This property is always synchronized with the user interface. In other words, When the user checks or unchecks enum values, the property value is updated to a new selection immediately. When the property is updated in the program – the user interface is updated to reflect the change.
When the user changes its selection by checking or unchecking enum values, The SelectionChanged
event is raised. You can use the Selected
property of the EnumFlagsSelector, which raised this event, to find out the newly selected value.
By default, the names of the enum values will be displayed in the user interface. While this is very convenient, sometimes this is not suitable (For example, a more detailed name should be displayed, the jargon used to name the values is unfamiliar to the target audience, or the values need to be translated to another language). In this case, You can set the AllowFormat
property and override the OnFormat
method. This method accepts the enum value to be displayed and should return a string representing the value displayed on the user interface.
What Is The Flags Attribute?
When decorated an enum type with the Flags
attribute, we notify the compiler that we want that a variable of this enum should be treated as a bit field. Unlike the default enum semantics, which allows us to store only one enum value (or list of mutually exclusive enum values) in a variable, The Flags attribute will enable us to keep many enum values in a variable. Therefore it can be used to store enum values that might occur in combination.
Here Some guidelines when creating this type of enum:
- We can use the bit manipulation operators (& for AND , | for OR , ^ for EXCLUSIVE OR) on those values.
- We should define enum values in powers of 2, that is, 1 (0001b) , 2 (0010b), 4 (0100b), 8 (1000b), and so on. This strategy will give the flags semantics by ensuring that those values can be freely combined using the bitwise OR operation and then be tested for existence using AND operation.
- You can also define a special value for commonly used combinations by using OR operator on previous declared values.
- You can also define value 0 as
None
– This special combination means that no flag is set.
The following demonstrate those guidelines Enum decorated with
Decorating Enum With Flags Attribute
[Flags]
enum Sample {
// special value - No flag set
N0 = 0,
// The flags - enum values in powers of 2
F0 = 1, // 001b , (F0 & F2) = N0 , (F0 & F1) = N0 , (F0 & F0) = F0
F1 = 2, // 010b , (F1 & F2) = N0 , (F1 & F1) = F1 , (F0 & F0) = N0
F2 = 4, // 100b , (F2 & F2) = F2 , (F2 & F1) = N0 , (F2 & F0) = N0
// commonly used combinations of the flags
C1 = F1 | F0 , // 011b , (C1 & F2) = N0 , (C1 & F1) = F1 , (C1 & F0) = F0
C2 = F2 | F0 , // 101b , (C2 & F2) = F2 , (C2 & F1) = N0 , (C2 & F0) = F0
C3 = F2 | F1 , // 110b , (C3 & F2) = F2 , (C3 & F1) = F1 , (C3 & F0) = N0
C4 = C1 | F2 , // 111b , (C4 & F2) = F2 , (C4 & F1) = F1 , (C4 & F0) = F0 , (C4 & C1) = C1
}
The FlagsHelper
encapsulates common operations on bit fields:
Common Operations On Bit Fields With FlagsHelper
public static class FlagsHelper {
// Find whether the set bits in checkBits are also set in flags variable
public static bool IsSet(this int flags,int checkBits) {
return ((flags & checkBits) == checkBits);
}
//-------------------------------------------------------------------------
// Set the set bits in setBits in flags variable
public static void Set(ref int flags,int setBits) {
flags |= setBits;
}
//-------------------------------------------------------------------------
// Clear the set bits clearBits in flags variable
public static void Clear(ref int flags,int clearBits) {
flags &= (~clearBits);
}
//-------------------------------------------------------------------------
// Clear all bits in flags variable
public static void Clear(ref int flags) {
flags = 0;
}
}
The following program show how can we use this class:
How to use FlagHelper?
static void Main(string[] args) {
int xx = 0; ; WriteBitField(xx); // 8 => False , 4 => False, 2 => False, 1 => False
FlagsHelper.Set (ref xx,8) ; WriteBitField(xx); // 8 => True , 4 => False, 2 => False, 1 => False
FlagsHelper.Set (ref xx,4) ; WriteBitField(xx); // 8 => True , 4 => True, 2 => False, 1 => False
FlagsHelper.Set (ref xx,1) ; WriteBitField(xx); // 8 => True , 4 => True, 2 => False, 1 => True
FlagsHelper.Clear(ref xx,4) ; WriteBitField(xx); // 8 => True , 4 => False, 2 => False, 1 => True
FlagsHelper.Clear(ref xx,1) ; WriteBitField(xx); // 8 => True , 4 => False, 2 => False, 1 => False
FlagsHelper.Set (ref xx,2) ; WriteBitField(xx); // 8 => True , 4 => False, 2 => True, 1 => False
FlagsHelper.Clear(ref xx ) ; WriteBitField(xx); // 8 => False , 4 => False, 2 => False, 1 => False
}
public static void WriteBitField(int xx) {
System.Console.WriteLine("8 => {0,5} , 4 => {1,5}, 2 => {2,5}, 1 => {3,5}"
,xx.IsSet(8) , xx.IsSet(4), xx.IsSet(2), xx.IsSet(1));
}
WinForms Demo – Select Many Enum Values
The demo program allows the user to show or hide 4 rectangles with different colors (red, green, yellow, blue). The user can also show or hide all rectangles and show and hide only the red and the blue rectangles. We create DisplayFlagsSelector
as EnumFlagsSelector
subclass and a new enum DisplayFlags
decorated with Flags attribute to implement this feature.

DisplayFlags Enum Decorated With Flags attribute
First, we define DisplayFlags
enum type with DisplayRed
, DisplayGreen
, DisplayYellow
and DisplayBlue
enum values. Please note that those values are powers of 2. We also define DisplayAll
and DispleyRedBlue
as combination of those flags.
DisplayFlags Enum Decorated With Flags attribute
[Flags]
public enum DisplayFlags {
DisplayRed = 0x0001,
DisplayGreen = 0x0002,
DisplayYellow = 0x0004,
DisplayBlue = 0x0008,
DisplayNone = 0,
DispleyRedBlue = DisplayRed | DisplayBlue,
DisplayAll = DisplayRed | DisplayGreen | DisplayYellow | DisplayBlue,
}
Now, we create DisplayFlagsSelector
with the this DisplayFlags
enum. With this custom WinForms control the user can select many enum values of this enum.
DisplayFlagsSelector To Select Many Enum Values Of DisplayFlags
public partial class DisplayFlagsSelector : EnumFlagsSelector<DisplayFlags> {
}
When the user update its selection, we update the Visible
property of the PictureBoxes.
The handler of the event SelectionChanged of DisplayFlagsSelector
private void winDisplayFlags_SelectionChanged(object sender,EventArgs ee) {
winBoxBlue.Visible = ((int)winDisplayFlags.Selected).IsSet((int)DisplayFlags.DisplayBlue);
winBoxRed.Visible = ((int)winDisplayFlags.Selected).IsSet((int)DisplayFlags.DisplayRed);
winBoxGreen.Visible = ((int)winDisplayFlags.Selected).IsSet((int)DisplayFlags.DisplayGreen);
winBoxYellow.Visible = ((int)winDisplayFlags.Selected).IsSet((int)DisplayFlags.DisplayYellow);
}
The Code Behind EnumSelector
Creating the basic control
To create the control, choose in the project context menu Add > New Item ... > Visual csharp Items > Windows Forms > UserControl
. Type the name “EnumFlagsSelector.cs” and click Add. A new design screen of the new user control appears. Drag a CheckedListBox control into the design view and update its properties (Name) to winCheckList
and Dock
to Fill
.

Adding enum values
As we want this control to display enum values we make it generic with the enum type TT
EnumFlagsSelector class
EnumFlagsSelector Inherits From UserControl
public partial class EnumFlagsSelector<TT> : UserControl {
In the constructor we fill winDropDown
with the enum values with help of Enum.GetValues
Adding enum values
EnumFlagsSelector – Add Enum Values
public EnumFlagsSelector() {
InitializeComponent();
foreach (object oo in Enum.GetValues(typeof(TT))) {
if ((int)oo != 0) {
winCheckList.Items.Add(oo,false);
}
}
}
SelectionChanged event
The SelectionChanged
event is raised when the selection is changed. The UpdateSelected
will raise this event when the _selected
field changed.
The SelectionChanged Event of EnumFlagsSelector
public event EventHandler SelectionChanged;
private void UpdateSelected(int selected) {
if (selected == _selected ) {
return;
}
_selected = selected;
if (SelectionChanged != null) {
SelectionChanged(this, new EventArgs());
}
}
The Selected property
The Selected
property should be synchronized with the user interface:
- In the property getter will return the
_selected
field - In the property setter – we will update the
_selected
field, RaiseSelectionChanged
event. We also updates the user interface. for each checkbox – we will check it if checkbox’s value is setted or uncheck it otherwise.
The Selected property of EnumFlagsSelector
public TT Selected {
get {
return (TT)((object)_selected);
}
set {
int valueInt = (int)((object)value);
if (_selected == valueInt) {
return;
}
_ignoreCheckEvent = true; // No Item check events while check/unchecking
for (int ii = 0; ii < winCheckList.Items.Count; ii++) {
winCheckList.SetItemChecked(ii, FlagsHelper.IsSet(valueInt ,(int)winCheckList.Items[ii]));
}
_ignoreCheckEvent = false;
UpdateSelected(valueInt);
}
}
private bool _ignoreCheckEvent;
private int _selected = 0;
Synchronize with user interface
To ensure that Selected
property getter will always return the selected values in the user interface, we will add a new handler winCheckList_ItemCheck
to winCheckList’s ItemCheck
event using the properties window.

In this handler we will update the field to reflect the GUI state and raise our SelectionChanged
event.
Synchronize user interface with The Selected property of EnumFlagsSelector
private void winCheckList_ItemCheck(object sender,ItemCheckEventArgs ee) {
if (_ignoreCheckEvent) { // will be true when called from selected property setter
return;
}
int selected = 0;
if (ee.NewValue == CheckState.Checked) {
FlagsHelper.Set(ref selected, (int)winCheckList.Items[ee.Index]);
}
for (int kk = 0; kk < winCheckList.Items.Count; kk++) {
if ( ee.Index != kk && winCheckList.GetItemCheckState(kk) == CheckState.Checked) {
FlagsHelper.Set(ref selected, (int)winCheckList.Items[kk]);
}
}
UpdateSelected(selected);
}
EnumSelector Summary
We see how can we create EnumFlagsSelector – a WinForms custom control to select many enum values. We also create a demo application. With the help of EnumFlagsSelector and minimal lines of code, we could create a specific control that allows to select many values of enum type.