1

I'm trying to create a custom designer or UITypeEditor and type converter for a custom type that I've created. I'd like to be able to use this editor in the Application Settings window so that my team and I can define this type for use in the settings of our creations.

That this point I've successfully created classes that serialize out to XML, but none of the attempts I've made to implement a designer or type converter have worked and most of the walk-throughs and examples I've been able to find on the topic discuss custom form elements, which is not what I'm after.

Ideally what I'd like is something similar to what one encounters when a font is added to the application settings. When editing the value of the setting a dialog allows the developer to easily define the properties of the type, which are then written out to the .config file. This is ideal, but at this point I'd settle for a type converter that actually produces standard values.

As I said, I can get the values out to the XML, I just can't figure out how to easily define those values. What approach should I take that would play well with the settings designer?

Edit

Here's where I'm at right now. I have class that acts as a proxy definition for an OpenFileDialog. The reason for this is outside the scope of this question, but, quickly, it has to do with UI elements that I'm controlling programmatically.

Here's the class:

Public Class FileSelection
Private _selectedFile As String
Public Property SelectedFile() As String
    Get
        Return _selectedFile
    End Get
    Set(ByVal value As String)
        _selectedFile = value
    End Set
End Property

Private _initialDir As String
Public Property InitialDirectory() As String
    Get
        Return _initialDir
    End Get
    Set(ByVal value As String)
        _initialDir = value
    End Set
End Property

Private _title As String
Public Property Title() As String
    Get
        Return _title
    End Get
    Set(ByVal value As String)
        _title = value
    End Set
End Property

Private _filter As String
Public Property Filter() As String
    Get
        Return _filter
    End Get
    Set(ByVal value As String)
        _filter = value
    End Set
End Property

End Class

The class in and of itself is doing what it should. But editing the properties of the class at design time is proving painful.

I've gotten as far as decorating the class like so: <SettingsSerializeAs(SettingsSerializeAs.Xml)> _ <TypeConverter(GetType(FileSelectionConverter))> _

With a type converter built, as far as I can, to the specs provided by Microsoft:

Public Class FileSelectionConverter
Inherits TypeConverter

Public Overrides Function CanConvertFrom(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal sourceType As System.Type) As Boolean

    If sourceType Is GetType(String) Then
        Return True
    End If

    Return MyBase.CanConvertFrom(context, sourceType)

End Function

Public Overrides Function ConvertFrom(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal culture As System.Globalization.CultureInfo, ByVal value As Object) As Object

    If TypeOf value Is String Then

        Dim v As String() = CStr(value).Split(",")
        Dim file As New FileSelection
        file.SelectedFile = Convert.ToString(v(0))
        file.InitialDirectory = Convert.ToString(v(1))
        file.Filter = Convert.ToString(v(2))
        file.Title = Convert.ToString(v(3))
        Return file

    End If

    Return MyBase.ConvertFrom(context, culture, value)

End Function

Public Overrides Function ConvertTo(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal culture As System.Globalization.CultureInfo, ByVal value As Object, ByVal destinationType As System.Type) As Object

    If destinationType Is GetType(String) Then

        Dim file As FileSelection
        file = CType(value, FileSelection)

        Return String.Format("{0},{1},{2},{3}", file.SelectedFile, file.InitialDirectory, file.Filter, file.Title)

    End If

    Return MyBase.ConvertTo(context, culture, value, destinationType)

End Function

Public Overrides Function GetStandardValuesSupported(ByVal context As System.ComponentModel.ITypeDescriptorContext) As Boolean
    Return True
End Function

Public Overrides Function GetStandardValues(ByVal context As System.ComponentModel.ITypeDescriptorContext) As System.ComponentModel.TypeConverter.StandardValuesCollection

    Dim values As New List(Of String)
    Dim file As New FileSelection

    file.SelectedFile = "<Selected File>"
    file.InitialDirectory = "<Initial Directory>"
    file.Filter = "Text files (*.txt)|*.txt|All files (*.*)|*.*"
    file.Title = "<Dialog Title>"

    values.Add(String.Format("{0},{1},{2},{3}", file.SelectedFile, file.InitialDirectory, file.Filter, file.Title))

    Dim svc As New StandardValuesCollection(values)

    Return svc

End Function

Public Overrides Function IsValid(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal value As Object) As Boolean
    Return True
End Function

End Class

The solution builds and run without issue, but I see absolutely nothing in the Settings designer when I add this class as type for use with a setting.

What's most frustrating about this is that I have no idea if the converter is working or not.

Any guidance would be appreciated.

4

1 回答 1

0

正如我在评论中提到的那样,在更改班级装饰后,我能够让类型转换器工作。有了它,我就可以使用 UITypeEditors 上的MSDN 文章来构建我想要的对话框。

这是代码(实际形式在其他地方处理):

Public Class FileSelectionEditor
Inherits System.Drawing.Design.UITypeEditor

Public Sub New()

End Sub

Public Overloads Overrides Function GetEditStyle(ByVal context As ITypeDescriptorContext) As UITypeEditorEditStyle

    Return UITypeEditorEditStyle.Modal

End Function

Public Overloads Overrides Function EditValue(ByVal context As ITypeDescriptorContext, ByVal provider As IServiceProvider, ByVal value As Object) As Object

    Dim edSvc As IWindowsFormsEditorService = CType(provider.GetService(GetType(IWindowsFormsEditorService)), IWindowsFormsEditorService)
    If edSvc Is Nothing Then
        Return Nothing
    End If

    If IsNothing(value) Then
        Dim file As New BATCORE.Configuration.FileSelection
        value = file
    End If

    Using form As New FileSelectionDialog(value)

        If edSvc.ShowDialog(form) = DialogResult.OK Then
            Return form.FileData
        End If

    End Using

    'If OK was not pressed, return the original value
    '
    Return value 
End Function

End Class

最后,在使用设计时代码时,有几件事让我很困惑:

  • Visual Studio 缓存设计时代码。为了对类型转换器或 UITypeEditor 进行更改,我发现我必须构建项目,然后关闭并重新打开解决方案。
  • Alt+Enter 是打开项目属性的快捷方式。用它。
  • 如果您想在设置设计器中使用自定义类型,这些类型必须存储在它们自己的项目/DLL 中。

我知道这篇文章长得可笑,但希望有人能够通过它并为自己的目的使用它。

于 2013-10-23T16:00:59.760 回答