Click here to Skip to main content
15,889,682 members
Articles / Programming Languages / C#
Article

A flag editor

Rate me:
Please Sign up or sign in to vote.
4.73/5 (34 votes)
17 Oct 2002 150.5K   739   65   23
This piece of code is the implementation of a simple flags editor. It can be used to edit flags in a property grid.

Sample Image - FlagsEditor.gif

Introduction

This editor displays a dropdown control holding a CheckedListBox with all the values of an enumeration.

Using the FlagsEditor

You just have to put the Editor attributes on an enumeration to link it with the FlagsEditor. A Description attribute can also be added to each value. It will be shown as a tooltip on the CheckedListBox items.

Here is a sample.

C#
[Flags,
  Editor(typeof(STUP.ComponentModel.Design.FlagsEditor), 
  typeof(System.Drawing.Design.UITypeEditor))]
public enum EnumerationTest
{
    [Description("Description for the first tested value.")]
    firstValue = 1,
    [Description("Description for the second tested value.")]
    secondValue = 2,
    [Description("Description for the third tested value.")]
    thirdValue = 4
}

How does it work ?

The Editor is just one class that inherits UITypeEditor. The behavior of Editor is controlled by two functions.

GetEditStyle

This function is used for controlling the appearance of the small button in the property grid. In this sample a dropdown arrow will be shown.

C#
public override UITypeEditorEditStyle 
       GetEditStyle(ITypeDescriptorContext context) 
{
    return UITypeEditorEditStyle.DropDown;
}

EditValue

This function is called when the user clicks on the small button.

C#
public override object EditValue(ITypeDescriptorContext context, 
        IServiceProvider provider, object value) 
{
    if (context != null
        && context.Instance != null
        && provider != null) 
    {

        // Get an instance of the IWindowsFormsEditorService. 
        edSvc = (IWindowsFormsEditorService)provider.GetService
                            (typeof(IWindowsFormsEditorService));

        if (edSvc != null) 
        {
            // Create a CheckedListBox
            clb = new CheckedListBox();

            ...

            // Show our CheckedListbox as a DropDownControl. 
            // This methods returns only when
            // the dropdowncontrol is closed
            edSvc.DropDownControl(clb);


            // return the right enum value
            // corresponding to the result
            return ...
        }
    }

    return value;
}

The DropDownControl can be closed by calling the edSvc.CloseDropDown() function.

For a complete example, just download the source file.

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


Written By
Web Developer
France France
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralVB.NET Port + Little Extra Feature Pin
The_Mega_ZZTer5-Aug-05 5:16
The_Mega_ZZTer5-Aug-05 5:16 
I ported the code to VB.NET using #Develop's nifty code translation tool for use in my own control... in addition, I added a feature... if the value of a flag is 0 (ie FontStyle.Regular) it will not appear in the listbox. So you can use, for example, the FontStyle enum and Regular will not appear in the list. By unchecking all other flags the 0 value will appear in the textbox. Smile | :)

I also included the fixes by James T. Johnson.

For those using the C# version who want this feature, here's how to implement it:

Find the foreach in the EditValue function and find the IntVal declaration. Right after that line put

if (IntVal > 0) {

and put the closing } right before the end of the for loop.

Here's the VB.NET code... note that the code translator unfortunately strips all comments... sorry for the inconvenience:

Imports System<br />
Imports System.Drawing.Design<br />
Imports System.Windows.Forms<br />
Imports System.Windows.Forms.Design<br />
Imports System.ComponentModel<br />
Imports System.Drawing<br />
<br />
Namespace System.Design<br />
<br />
    Public Class FlagsEditor<br />
        Inherits UITypeEditor<br />
<br />
        Friend Class clbItem<br />
<br />
            Public Sub New(ByVal str As String, ByVal value As Integer, ByVal tooltip As String)<br />
                Me.str = str<br />
                Me._value = value<br />
                Me._tooltip = tooltip<br />
            End Sub<br />
            Private str As String<br />
            Private _value As Integer<br />
<br />
            Public ReadOnly Property Value() As Integer<br />
                Get<br />
                    Return _value<br />
                End Get<br />
            End Property<br />
            Private _tooltip As String<br />
<br />
            Public ReadOnly Property Tooltip() As String<br />
                Get<br />
                    Return _tooltip<br />
                End Get<br />
            End Property<br />
<br />
            Public Overloads Overrides Function ToString() As String<br />
                Return str<br />
            End Function<br />
        End Class<br />
        Private edSvc As IWindowsFormsEditorService = Nothing<br />
        Private clb As CheckedListBox<br />
        Private tooltipControl As ToolTip<br />
<br />
        Public Overloads Overrides Function EditValue(ByVal context As ITypeDescriptorContext, ByVal provider As IServiceProvider, ByVal value As Object) As Object<br />
            If Not (context Is Nothing) AndAlso Not (context.Instance Is Nothing) AndAlso Not (provider Is Nothing) Then<br />
                edSvc = CType(provider.GetService(GetType(IWindowsFormsEditorService)), IWindowsFormsEditorService)<br />
                If Not (edSvc Is Nothing) Then<br />
                    clb = New CheckedListBox<br />
                    clb.BorderStyle = BorderStyle.FixedSingle<br />
                    clb.CheckOnClick = True<br />
                    AddHandler clb.MouseDown, AddressOf Me.OnMouseDown<br />
                    AddHandler clb.MouseMove, AddressOf Me.OnMouseMoved<br />
                    tooltipControl = New tooltip<br />
                    tooltipControl.ShowAlways = True<br />
                    For Each name As String In [Enum].GetNames(context.PropertyDescriptor.PropertyType)<br />
                        Dim enumVal As Object = [Enum].Parse(context.PropertyDescriptor.PropertyType, name)<br />
                        Dim intVal As Integer = CType(Convert.ChangeType(enumVal, GetType(Integer)), Integer)<br />
                        If intVal > 0 Then<br />
                            Dim fi As System.Reflection.FieldInfo = context.PropertyDescriptor.PropertyType.GetField(name)<br />
                            Dim attrs As DescriptionAttribute() = CType(fi.GetCustomAttributes(GetType(DescriptionAttribute), False), DescriptionAttribute())<br />
                            Dim tooltip As String<br />
                            If attrs.Length > 0 Then<br />
                                tooltip = attrs(0).Description<br />
                            Else<br />
                                tooltip = ""<br />
                            End If<br />
                            Dim intEdited As Integer = CType(Convert.ChangeType(value, GetType(Integer)), Integer)<br />
                            Dim item As clbItem = New clbItem(enumVal.ToString, intVal, tooltip)<br />
                            Dim checkedItem As Boolean = ((intEdited And intVal) = intVal)<br />
                            clb.Items.Add(item, checkedItem)<br />
                        End If<br />
                    Next<br />
                    edSvc.DropDownControl(clb)<br />
                    Dim result As Integer = 0<br />
                    For Each obj As clbItem In clb.CheckedItems<br />
                        result = result Or obj.Value<br />
                    Next<br />
                    Return [Enum].ToObject(context.PropertyDescriptor.PropertyType, result)<br />
                End If<br />
            End If<br />
            Return value<br />
        End Function<br />
<br />
        Public Overloads Overrides Function GetEditStyle(ByVal context As ITypeDescriptorContext) As UITypeEditorEditStyle<br />
            Return UITypeEditorEditStyle.DropDown<br />
        End Function<br />
        Private handleLostfocus As Boolean = False<br />
<br />
        Private Sub OnMouseDown(ByVal sender As Object, ByVal e As MouseEventArgs)<br />
            If Not handleLostfocus AndAlso clb.ClientRectangle.Contains(clb.PointToClient(New Point(e.X, e.Y))) Then<br />
                AddHandler clb.LostFocus, AddressOf Me.ValueChanged<br />
                handleLostfocus = True<br />
            End If<br />
        End Sub<br />
<br />
        Private Sub OnMouseMoved(ByVal sender As Object, ByVal e As MouseEventArgs)<br />
            Dim index As Integer = clb.IndexFromPoint(e.X, e.Y)<br />
            If index >= 0 Then<br />
                tooltipControl.SetToolTip(clb, CType(clb.Items(index), clbItem).Tooltip)<br />
            End If<br />
        End Sub<br />
<br />
        Private Sub ValueChanged(ByVal sender As Object, ByVal e As EventArgs)<br />
            If Not (edSvc Is Nothing) Then<br />
                edSvc.CloseDropDown()<br />
            End If<br />
        End Sub<br />
    End Class<br />
End Namespace

Generalcant get the zip file Pin
Paul Ashton14-Apr-05 1:10
Paul Ashton14-Apr-05 1:10 
GeneralRe: cant get the zip file Pin
The_Mega_ZZTer5-Aug-05 5:15
The_Mega_ZZTer5-Aug-05 5:15 
GeneralThank You Pin
Dave Mc Kenzie14-Oct-04 22:26
Dave Mc Kenzie14-Oct-04 22:26 
QuestionHow to use this concept for other types? Pin
DerSebastian4-Oct-04 3:29
DerSebastian4-Oct-04 3:29 
AnswerRe: How to use this concept for other types? Pin
Eric P Schneider9-Nov-05 12:15
Eric P Schneider9-Nov-05 12:15 
GeneralNice Job! Pin
glusk30-Aug-04 9:52
glusk30-Aug-04 9:52 
GeneralFlag Editor Pin
Fregate18-Dec-03 19:10
Fregate18-Dec-03 19:10 
GeneralRe: Flag Editor Pin
ShyH26-Jan-04 20:02
ShyH26-Jan-04 20:02 
GeneralIt took... Pin
James T. Johnson28-May-03 1:32
James T. Johnson28-May-03 1:32 
GeneralRe: It took... Pin
Nnamdi Onyeyiri28-May-03 3:45
Nnamdi Onyeyiri28-May-03 3:45 
GeneralIgnore the people Pin
Pete Bassett6-Dec-02 1:16
Pete Bassett6-Dec-02 1:16 
GeneralRe: Ignore the people Pin
Virender Sandhu9-Feb-03 10:28
Virender Sandhu9-Feb-03 10:28 
Questionumm ... I second the ... What is this exactly ? Pin
Anonymous18-Oct-02 17:17
Anonymous18-Oct-02 17:17 
AnswerRe: umm ... I second the ... What is this exactly ? Pin
James T. Johnson18-Oct-02 17:46
James T. Johnson18-Oct-02 17:46 
GeneralRe: umm ... I second the ... What is this exactly ? Pin
Philippe Lhoste22-Oct-02 6:32
Philippe Lhoste22-Oct-02 6:32 
GeneralRe: umm ... I second the ... What is this exactly ? Pin
stestagg10-Jul-08 2:01
stestagg10-Jul-08 2:01 
Questionumm...what is this exactly? Pin
Marc Clifton18-Oct-02 11:13
mvaMarc Clifton18-Oct-02 11:13 
AnswerRe: umm...what is this exactly? Pin
Ed.Poore24-Aug-06 5:09
Ed.Poore24-Aug-06 5:09 
GeneralRe: umm...what is this exactly? Pin
Marc Clifton24-Aug-06 8:07
mvaMarc Clifton24-Aug-06 8:07 
GeneralRe: umm...what is this exactly? Pin
Ed.Poore24-Aug-06 8:19
Ed.Poore24-Aug-06 8:19 
GeneralRe: umm...what is this exactly? Pin
peterchen11-Apr-07 3:01
peterchen11-Apr-07 3:01 
General!wow Pin
NormDroid18-Oct-02 7:56
professionalNormDroid18-Oct-02 7:56 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.