Build enums (flags) in the designer of Visual Studio

I have an enumeration of data types that can be displayed in a .NET Forms control, and I want to provide an interface for the control's users to filter some types (set some of the flags). The bit field seems to be a logical way to do this, unfortunately, the enumeration starts with 0, and not with 1 (0, 1, 2, 4, 8, ...) and cannot be changed.

How can I open this set of flags so that it can be easily configured programmatically or through the Visual Studio constructor?

+3
source share
2 answers

UITypeEditor [EditorAttribute].

, - , , , , .

- - HashSet<T> - List<T>, .NET 2.0/3.0, .

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing.Design;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.Design;

public class MyControl : UserControl
{
    public MyControl()
    {
        Values = new HashSet<MyEnum>();
    }
    [Editor(typeof(MyEnumSetEditor), typeof(UITypeEditor))]
    [TypeConverter(typeof(MyEnumSetConverter))]
    public HashSet<MyEnum> Values { get; set; }
}

public enum MyEnum
{  // numbers as per the question...
    A = 0, B = 1, C = 2, D = 4, E = 8
}
class MyEnumSetEditor : EnumSetEditor<MyEnum> { }
class MyEnumSetConverter : EnumSetConverter<MyEnum> { }

// from here down is shared between types
abstract class EnumSetConverter<T> : TypeConverter where T : struct
{
    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
    {
        return destinationType == typeof(string) || base.CanConvertTo(context, destinationType);
    }
    public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
    {
        if(destinationType == typeof(string))
        {
            HashSet<T> set = (HashSet<T>)value;
            if (set == null) return "(null)";

            StringBuilder sb = new StringBuilder();
            foreach (T item in Enum.GetValues(typeof(T)))
            {
                if (set.Contains(item))
                {
                    if (sb.Length > 0) sb.Append(", ");
                    sb.Append(item);
                }
            }
            return sb.ToString();
        }
        return base.ConvertTo(context, culture, value, destinationType);
    }
}

public abstract class EnumSetEditor<T> : UITypeEditor where T : struct
{
    public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
    {
        return UITypeEditorEditStyle.DropDown;
    }
    public override bool IsDropDownResizable
    {
        get { return true; }
    }
    public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
    {
        IWindowsFormsEditorService svc = (IWindowsFormsEditorService)
            provider.GetService(typeof(IWindowsFormsEditorService));
        HashSet<T> set = value as HashSet<T>;
        if (svc != null && set != null)
        {
            UserControl ctrl = new UserControl();
            CheckedListBox clb = new CheckedListBox();
            clb.Dock = DockStyle.Fill;
            Button btn = new Button();
            btn.Dock = DockStyle.Bottom;
            foreach (T item in Enum.GetValues(typeof(T)))
            {
                clb.Items.Add(item, set.Contains(item));
            }
            ctrl.Controls.Add(clb);
            ctrl.Controls.Add(btn);
            btn.Text = "OK";
            btn.Click += delegate
            {
                set.Clear();
                foreach (T item in clb.CheckedItems)
                {
                    set.Add(item);
                }
                svc.CloseDropDown();
            };
            svc.DropDownControl(ctrl);
        }

        return value;
    }
}
+4

: , . , . DesignTime, PropertyGrid Microsoft:

UITypeEditor, , . , UITypeEditor .

, , Marc. , , , , .

:

  • (: MyFlags) (: MyProperty), .
  • (: EnumEditorControl), .
  • UITypeEditor (: EnumEditor); Editor. EnumEditorControl.
  • TypeConverter (: EnumConverter); (TypeConverter) .

:

  • Enum Flags.

    <Flags>
    Public Enum MyFlags
        Flag1 = 2 ^ 0
        Flag2 = 2 ^ 1
        Flag3 = 2 ^ 2
    End Enum
    
  • .

    Public Property MyProperty() As MyFlags
        ...
    End Property
    

, (. # 6).

  1. , .

    Imports System.Windows.Forms.Design
    Public Class EnumEditorControl(Of T As Structure)
        Public Sub New(value As Long, editorService As IWindowsFormsEditorService)
            'This call is required by the Windows.Forms Form Designer.
            InitializeComponent()
    
            _value = value
            _editorService = editorService
    
            For Each item As Long In [Enum].GetValues(GetType(T))
                Me.CheckedListBox1.Items.Add([Enum].GetName(GetType(T), item), (_value And item) = item)
            Next
    
        End Sub
    
        Private _value As Long
        Public Property Value As Long
            Get
                Return _value
            End Get
            Set(value As Long)
                _value = value
            End Set
        End Property
        Private _editorService As IWindowsFormsEditorService
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Dim v As Long = 0
            For Each item As String In Me.CheckedListBox1.CheckedItems
                v = (v Or [Enum].Parse(GetType(T), item))
            Next
            _value = v
            Me._editorService.CloseDropDown()
        End Sub
    End Class
    

designer.vb. : value editorService, ( ) " ", value ( ) , , Me._editorService.CloseDropDown().

  1. UITypeEditor.

    Imports System.ComponentModel
    Imports System.Drawing.Design
    Imports System.Windows.Forms.Design
    
    Public Class EnumEditor(Of T As Structure)
        Inherits UITypeEditor
    
        Public Overrides Function GetEditStyle(context As ITypeDescriptorContext) As UITypeEditorEditStyle
            Return UITypeEditorEditStyle.DropDown
        End Function
        Public Overrides ReadOnly Property IsDropDownResizable() As Boolean
            Get
                Return True
            End Get
        End Property
        Public Overrides Function EditValue(context As ITypeDescriptorContext, provider As IServiceProvider, value As Object) As Object
            Dim svc As IWindowsFormsEditorService = DirectCast(provider.GetService(GetType(IWindowsFormsEditorService)), IWindowsFormsEditorService)
            Dim items As Long = CLng(value)
            If svc IsNot Nothing Then
                Dim c As New EnumEditorControl(Of T)(value, svc)
    
                svc.DropDownControl(c)
    
                value = c.Value
            End If
    
            Return CType(value, T)
        End Function
    End Class
    

- EditValue, (. # 3) svc.DropDownControl(c). , , .

  1. TypeConverter, , .    System.ComponentModel    System.Drawing.Design    System.Text    System.Windows.Forms.Design

    Class EnumConverter(Of T As Structure)
        Inherits TypeConverter
    
        Public Overrides Function CanConvertTo(context As ITypeDescriptorContext, destinationType As Type) As Boolean
            Return destinationType = GetType(String) OrElse MyBase.CanConvertTo(context, destinationType)
        End Function
        Public Overrides Function ConvertTo(context As ITypeDescriptorContext, culture As System.Globalization.CultureInfo, value As Object, destinationType As Type) As Object
            If destinationType = GetType(String) Then
                Dim items As Integer = CLng(value)
    
                If items = 0 Then
                    Return ""
                End If
    
                Dim values As New List(Of String)
    
                For Each item As Integer In [Enum].GetValues(GetType(T))
                    If (items And item) = item Then
                        values.Add([Enum].GetName(GetType(T), item))
                    End If
                Next
                Return String.Join(", ", values)
            End If
    
            Return MyBase.ConvertTo(context, culture, value, destinationType)
        End Function
    End Class
    
  2. , (. # 2).

    <Browsable(True),
    DefaultValue(MyFlags.Flag1),
    Editor(GetType(EnumEditor(Of MyFlags)), 
    GetType(System.Drawing.Design.UITypeEditor)),
    TypeConverter(GetType(EnumConverter(Of MyFlags)))
    >
    Public Property MyProperty() As MyFlags
        ...
    End Property
    

. " ", : , .

0

Source: https://habr.com/ru/post/1707810/


All Articles