Discussion:
PropertyDescriptor for Generic.List(Of String)?
(too old to reply)
WALDO
2007-06-01 20:59:02 UTC
Permalink
I have an object which I would like to show on a property grid. The object
has a property that ultimately can boil down to an array of unique strings.
I though I'd be clever and code it as a Generic.List(Of String).

When I select the object so it is shown in a PropertyGrid, it, shows the
default collection editor. So far, so good. When I go to add a value, the
collection editor complains that it can't find a constructor for type
System.String.

That makes sense to me, given that a string doesn't have a parameter-less
constructor.

Does anyone know of a quick-and-dirty way to have an editable property of
strings that will cooperate with the default collection editor in the
fashion I would like? I want to know If I am overthinking it before I create
a custom TypeDescriptor and a custom CollectionEditor.


Any help is appreciated.
Thanks in advance.

WALDO
VisualHint
2007-06-01 21:44:35 UTC
Permalink
Hello Waldo,

if you want to get the true string collection editor, decorate your
property with:
[Editor("System.Windows.Forms.Design.StringCollectionEditor,
System.Design, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a",
typeof(System.Drawing.Design.UITypeEditor))]

Or else, if you want to fix the generic collection editor, implement
something like described on this page:
http://www.dotnet247.com/247reference/msgs/30/153300.aspx
The method CreateInstance of your editor must return an empty string.

Best regards,

Nicolas Cadilhac @ VisualHint (http://www.visualhint.com)
Home of Smart FieldPackEditor.Net / DateTimePicker replacement
Home of Smart PropertyGrid for .Net and MFC
Microsoft PropertyGrid Resource List - http://www.propertygridresourcelist.com
Post by WALDO
I have an object which I would like to show on a property grid. The object
has a property that ultimately can boil down to an array of unique strings.
I though I'd be clever and code it as a Generic.List(Of String).
When I select the object so it is shown in aPropertyGrid, it, shows the
default collection editor. So far, so good. When I go to add a value, the
collection editor complains that it can't find a constructor for type
System.String.
That makes sense to me, given that a string doesn't have a parameter-less
constructor.
Does anyone know of a quick-and-dirty way to have an editable property of
strings that will cooperate with the default collection editor in the
fashion I would like? I want to know If I am overthinking it before I create
a custom TypeDescriptor and a custom CollectionEditor.
Any help is appreciated.
Thanks in advance.
WALDO
WALDO
2007-06-02 14:33:57 UTC
Permalink
Yeah, I bit the bullet.

Imports System.Drawing.Design
Imports System.ComponentModel
Imports System.ComponentModel.Design

Public Class PathCollectionEditor
Inherits CollectionEditor

Public Sub New()
MyBase.New(GetType(Generic.List(Of String)))
End Sub

Protected Overrides Function CreateCollectionItemType() As System.Type
Return GetType(FolderPath)
End Function

Protected Overrides Function CanSelectMultipleInstances() As Boolean
Return False
End Function

Protected Overrides Function GetDisplayText(ByVal value As Object) As String
Dim displayText As String = String.Empty
Dim folder As FolderPath = CType(value, FolderPath)
Dim fld As String = folder.Path

If (String.IsNullOrEmpty(fld) = False) Then
Try
Dim di As New IO.DirectoryInfo(fld)
displayText = di.Name
Catch ex As Exception
End Try
End If

If (String.IsNullOrEmpty(displayText) = True) Then
displayText = "[Folder]"
End If

Return displayText
End Function

Protected Overrides Function CreateCollectionForm() As System.ComponentModel.Design.CollectionEditor.CollectionForm
Dim frm As CollectionEditor.CollectionForm = MyBase.CreateCollectionForm()
frm.Font = New Font("Tahoma", 8.25!)
frm.Text = "Edit Folders"
frm.HelpButton = False

'TableLayoutPanel: overArchingTableLayoutPanel
' Button: downButton
' TableLayoutPanel: addRemoveTableLayoutPanel
' Label: propertiesLabel
' Label: membersLabel
' FilterListBox: ListBox
' VsPropertyGrid: propertyBrowser
' TableLayoutPanel: okCancelTableLayoutPanel
' Button: upButton

Dim overArchingTableLayoutPanel As TableLayoutPanel = frm.Controls.Item("overArchingTableLayoutPanel")
If (Not overArchingTableLayoutPanel Is Nothing) Then
Dim propertyBrowser As PropertyGrid = overArchingTableLayoutPanel.Controls.Item("propertyBrowser")
If (Not propertyBrowser Is Nothing) Then
propertyBrowser.PropertySort = PropertySort.Alphabetical
propertyBrowser.ToolbarVisible = False
End If
End If

'For Each ctrl As Control In frm.Controls.Item("overArchingTableLayoutPanel").Controls
' Debug.WriteLine(ctrl.Name, ctrl.GetType().Name)
'Next

Return frm
End Function

''' <summary>
''' Gets the list of items to fill the editor.
''' </summary>
''' <param name="editValue">The source property</param>
''' <returns>Returns an IList items to populate the collection editor with.</returns>
Protected Overrides Function GetItems(ByVal editValue As Object) As Object()
'MsgBox(editValue.GetType().Name, , "GetItems")
Dim lst As New Generic.List(Of FolderPath)
For Each path As String In editValue
lst.Add(New FolderPath(path))
Next
Return lst.ToArray()
End Function

''' <summary>
''' Takes the items from the editor and reapplies them to the source property.
''' </summary>
''' <param name="editValue">The source property</param>
''' <param name="value">List of items from the editor.</param>
Protected Overrides Function SetItems(ByVal editValue As Object, ByVal value() As Object) As Object
'MsgBox(editValue.GetType().Name & ", " & value.GetType().Name, , "SetItems")
Dim values As New Generic.List(Of String)
Dim uniquity As New Generic.List(Of String)
For i As Integer = 0 To value.Length - 1
Dim o As Object = value(i)
Dim path As String = String.Empty
If TypeOf o Is String Then
path = CStr(o)
ElseIf TypeOf o Is FolderPath Then
path = CType(o, FolderPath).Path
End If
If (String.IsNullOrEmpty(path) = False) Then
If (uniquity.Contains(path.ToLower()) = False) Then
uniquity.Add(path.ToLower())
values.Add(path)
End If
End If
Next
Return MyBase.SetItems(editValue, values.ToArray())
End Function

End Class

Public Class FolderPath

Private _path As String = String.Empty

<Editor(GetType(PathEditor), GetType(UITypeEditor))> _
Public Property Path() As String
Get
Return Me._path
End Get
Set(ByVal Value As String)
If (String.IsNullOrEmpty(Value) = True) Then Value = String.Empty
Me._path = Value
End Set
End Property
Private Function ShouldSerializePath() As Boolean
Return False
End Function
Private Sub ResetPath()
Me.Path = String.Empty
End Sub

Public Sub New()
End Sub

Public Sub New(ByVal path As String)
MyClass.New()
Me.Path = path
End Sub

End Class

Public Class PathEditor
Inherits UITypeEditor

Public Sub New()
MyBase.New()
End Sub

Public Overrides Function EditValue(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal provider As System.IServiceProvider, ByVal value As Object) As Object
Dim path As String = CStr(value)
Dim dlg As New FolderBrowserDialog
dlg.SelectedPath = path
dlg.Description = "Select folder"
Dim res As DialogResult = DialogResult.Cancel
res = dlg.ShowDialog()
If (res = DialogResult.OK) Then
path = dlg.SelectedPath
End If
Return path
End Function

Public Overrides Function GetEditStyle(ByVal context As System.ComponentModel.ITypeDescriptorContext) As System.Drawing.Design.UITypeEditorEditStyle
Return UITypeEditorEditStyle.Modal
End Function

End Class
Post by VisualHint
Hello Waldo,
if you want to get the true string collection editor, decorate your
[Editor("System.Windows.Forms.Design.StringCollectionEditor,
System.Design, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a",
typeof(System.Drawing.Design.UITypeEditor))]
Or else, if you want to fix the generic collection editor, implement
http://www.dotnet247.com/247reference/msgs/30/153300.aspx
The method CreateInstance of your editor must return an empty string.
Best regards,
Home of Smart FieldPackEditor.Net / DateTimePicker replacement
Home of Smart PropertyGrid for .Net and MFC
Microsoft PropertyGrid Resource List - http://www.propertygridresourcelist.com
Post by WALDO
I have an object which I would like to show on a property grid. The object
has a property that ultimately can boil down to an array of unique strings.
I though I'd be clever and code it as a Generic.List(Of String).
When I select the object so it is shown in aPropertyGrid, it, shows the
default collection editor. So far, so good. When I go to add a value, the
collection editor complains that it can't find a constructor for type
System.String.
That makes sense to me, given that a string doesn't have a parameter-less
constructor.
Does anyone know of a quick-and-dirty way to have an editable property of
strings that will cooperate with the default collection editor in the
fashion I would like? I want to know If I am overthinking it before I create
a custom TypeDescriptor and a custom CollectionEditor.
Any help is appreciated.
Thanks in advance.
WALDO
Loading...