views:

43

answers:

2

I have a UserControl that exposes a System.Type property. I want to make it settable at design time, like the BindingSource's DataSource property. Ultimately, I would like the designer code to generate this:

this.EntityType = typeof(Company.Product.Class);

Where the class selection would come from the project's registered Data Sources.

Right now I'm exposing a BindingSource directly for the effect, but I'd love to know how can I replicate its behavior for my control.

+1  A: 

You'll need a TypeConverter to convert between the string representation of the type, as displayed in the Properties window, and the Type. You are very unspecific in your question so I'll just punt an answer. A good candidate is the TypeListConverter class, it already does the heavy lifting. You just need to derive your own and call the base constructor with a list of the Types you accept:

  public partial class UserControl1 : UserControl {
    public UserControl1() {
      InitializeComponent();
    }
    [TypeConverter(typeof(myTypeTypeConverter))]
    public Type Type { get; set; }

    private class myTypeTypeConverter : TypeListConverter {
      private static Type[] types = new Type[] { typeof(int), typeof(string), typeof(long) };
      public myTypeTypeConverter() : base(types) {}
    }
  }

After you drop this control on a form, you can use the combobox for the Type property and choose between the three types. If this is not suitable then you'll have to make your own TypeConverter. Use Reflector to have a look at TypeListConverter. It isn't very big.

Hans Passant
Arggg, I got interuppted, and you said the same as me :( +1 anyways.
leppie
The BindingSource lets me pick from the project's Data Sources, which can be any type in any referenced project. Just having a static list of types isn't of much use considering the types it'll use will almost always come from other assemblies.
Ilia Jerebtsov
@Ilia, you still failed to explain exactly *which* types need to be available. I explained at the bottom of my post how to get your own type converter going.
Hans Passant
@Hans: All of them. Like the BindingSource does to bind to a business object.
Ilia Jerebtsov
+1  A: 

This post helped me with this same type of problem.

http://stackoverflow.com/questions/2760544/visual-studio-design-time-property-form-list-drop-down

This is my implementation, it creates a drop down of types that are accessible from the current project, and filters them by their base class.

You have to add a reference to EnvDTE

    Public Class EditChildFormDesignerTypeEditor
    Inherits UITypeEditor

    Public Overrides Function GetEditStyle(ByVal context As ITypeDescriptorContext) As UITypeEditorEditStyle
        Return UITypeEditorEditStyle.DropDown
    End Function

    Public Overrides Function EditValue(ByVal context As ITypeDescriptorContext, ByVal provider As IServiceProvider, ByVal value As Object) As Object
        Dim edSvc = DirectCast(provider.GetService(GetType(IWindowsFormsEditorService)), IWindowsFormsEditorService)


        Dim dte As EnvDTE.DTE = context.GetService(GetType(EnvDTE.DTE))
        If dte Is Nothing Then Throw New InvalidOperationException("DTE not found.")

        Dim lb As New ListBox()

        For Each proj As Project In dte.Solution.Projects
            For Each ce As CodeElement In proj.CodeModel.CodeElements
                If ce.Kind = vsCMElement.vsCMElementClass Then
                    Dim ccl As CodeClass = ce
                    If ccl.IsDerivedFrom(GetType(frmEditChildItem).FullName) Then
                        Dim Tp As Type = Type.GetType(ccl.FullName)
                        If Tp IsNot Nothing Then
                            lb.Items.Add(Tp)
                        End If
                    End If
                End If
            Next
        Next

        If value IsNot Nothing Then
            lb.SelectedItem = value
        End If

        edSvc.DropDownControl(lb)

        value = DirectCast(lb.SelectedItem, Type)

        Return value
    End Function
End Class
Kratz
Thank you, this is what I was looking for.
Ilia Jerebtsov