vb.netwinformscustom-controlsdesign-timeuitypeeditor

How do I make a property of a custom control open a file dialog?


I have a custom control with a property that holds the name (full path) to a file location that exists on the target computer.

The exact path will vary according to type of target pc and is typically set right after I add the custom control to my Form, while I am still in design mode of my project, so that when my application runs, it picks up the filename from the property.

It would be convenient if the property opened a file dialog to let me browse to the location (similar to how dialogs are opened when browsing for image and color properties), but this doesn't seem to be possible in visual basic.

After googling for days I have found a couple of articles that touch the subject for other programming languages (see example snippet below) but I haven't been able to work out how to make it work for visual basic.

Here is a snippet I found that mentions the use of an editor, which may be a clue to get started.

[Editor(typeof(FileSelectorTypeEditor), typeof(UITypeEditor))]
public string Filename
{
   get { return _filename; }
   set { _filename = value; }
}

Hope someone out there can lead me in the right way.


Solution

  • FileSelectorTypeEditor is probably a custom class derived from either FileNameEditor or FolderNameEditor.

    You can implement both, using the standard class or extend the default with your own, as you have seen in those C# sources you have found.

    Here I'm using a specialized FileNameEditor class, named (with some lack of imagination) SpecializedFileNameEditor and the standard FolderNameEditor assigning the UITypeEditor to two properties of a class.

    ► The ImagePath property editor is the SpecializedFileNameEditor object, which uses an OpenFileDialog, where a filter is pre-selected. It also overrides the EditValue method, to set the current value, if any, of an associated property (here, ImagePath) as the InitialDirectory of the OpenFileDialog.
    ► The ImageFolder property editor is a standard FolderNameEditor, which opens a FolderBrowserDialog.

    I'm also attaching an ExpandableObjectConverter type converter, so you can present the two properties as an expandable property selector in a PropertyGrid.

    You can see an example here:
    How to bind child Controls of a User Control to a Public Property

    Imports System.ComponentModel
    Imports System.Drawing.Design
    Imports System.IO
    Imports System.Windows.Forms
    Imports System.Windows.Forms.Design
    
    <TypeConverter(GetType(ExpandableObjectConverter))>
    Public Class ImagePickerClass
    
        Public Sub New()  
            ' Initialize [...]
        End Sub
    
        <Editor(GetType(SpecializedFileNameEditor), GetType(UITypeEditor))>
        Public Property ImagePath As String
    
        <Editor(GetType(FolderNameEditor), GetType(UITypeEditor))>
        Public Property ImageFolder As String
    
        Public Class SpecializedFileNameEditor
            Inherits FileNameEditor
    
            Private currentValue As String = String.Empty
    
            Public Overrides Function EditValue(context As ITypeDescriptorContext, provider As IServiceProvider, value As Object) As Object
                If TypeOf value Is String Then
                    currentValue = DirectCast(value, String)
                End If
                Return MyBase.EditValue(context, provider, value)
            End Function
    
            Protected Overrides Sub InitializeDialog(ofd As OpenFileDialog)
                MyBase.InitializeDialog(ofd)
                If Not currentValue.Equals(String.Empty) Then
                    ofd.InitialDirectory = Path.GetDirectoryName(currentValue)
                End If
                ofd.Filter = "PNG Images (*.png)|*.png"
            End Sub
        End Class
    End Class