Groups | Blog | Home
all groups > dotnet windows forms designtime > june 2007 >

dotnet windows forms designtime : PropertyDescriptor for Generic.List(Of String)?


WALDO
6/1/2007 4:59:02 PM
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
6/1/2007 9:44:35 PM
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


[quoted text, click to view]

WALDO
6/2/2007 10:33:57 AM
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 =3D String.Empty
Dim folder As FolderPath =3D CType(value, FolderPath)
Dim fld As String =3D folder.Path

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

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

Return displayText
End Function

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

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

Dim overArchingTableLayoutPanel As TableLayoutPanel =3D =
frm.Controls.Item("overArchingTableLayoutPanel")
If (Not overArchingTableLayoutPanel Is Nothing) Then
Dim propertyBrowser As PropertyGrid =3D =
overArchingTableLayoutPanel.Controls.Item("propertyBrowser")
If (Not propertyBrowser Is Nothing) Then
propertyBrowser.PropertySort =3D =
PropertySort.Alphabetical
propertyBrowser.ToolbarVisible =3D 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=3D"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=3D"editValue">The source property</param>
''' <param name=3D"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 =3D 0 To value.Length - 1
Dim o As Object =3D value(i)
Dim path As String =3D String.Empty
If TypeOf o Is String Then
path =3D CStr(o)
ElseIf TypeOf o Is FolderPath Then
path =3D CType(o, FolderPath).Path
End If
If (String.IsNullOrEmpty(path) =3D False) Then
If (uniquity.Contains(path.ToLower()) =3D 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 =3D 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) =3D True) Then Value =3D =
String.Empty
Me._path =3D Value
End Set
End Property
Private Function ShouldSerializePath() As Boolean
Return False
End Function
Private Sub ResetPath()
Me.Path =3D String.Empty
End Sub

Public Sub New()
End Sub

Public Sub New(ByVal path As String)
MyClass.New()
Me.Path =3D 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 =3D CStr(value)
Dim dlg As New FolderBrowserDialog
dlg.SelectedPath =3D path
dlg.Description =3D "Select folder"
Dim res As DialogResult =3D DialogResult.Cancel
res =3D dlg.ShowDialog()
If (res =3D DialogResult.OK) Then
path =3D 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


[quoted text, click to view]
AddThis Social Bookmark Button