1

In Windows Forms, I'm representing a custom class in a PropertyGid control, which has various string properties as you can notice in the next image:

enter image description here

The problem is that I'm not totally satisfied with the current behavior for changing the value of the string properties. For those properties that expects a file or directory path, like "Target" or "Working Directory" properties, I would like to know if it could be possible and viable to implement a TypeConverter / Type Descriptor that would open a OpenFileDialog when clicking in the down arrow at the right of the field in the property grid. That is, to select a file or folder through a OpenFileDialog, instead of directly writing the path in the property grid, but still letting the option to directly write the path if I want to do so.

Maybe .NET Framework class library already provides the TypeConverter / TypeDescriptor that I'm requesting?. If not, is this possible to do?. And how to start doing so?.

Or any other idea to be able open a OpenFileDialog to change the value of a specific property in a PropertyGrid control?.

ElektroStudios
  • 19,105
  • 33
  • 200
  • 417
  • 1
    The framework doesn't know anything about IShellLink. Create a modal UITypeEditor to customize value editing. – Hans Passant May 28 '19 at 12:59
  • @Hans Passant Thanks for comment. I will start by practicing with the code example at: learn.microsoft.com/en-us/dotnet/api/system.drawing.design.uitypeeditor?view=netframework-4.8, but I will remark that those properties are of string data-type. – ElektroStudios May 28 '19 at 13:05
  • Apparently there is a built-in UITypeEditor with class name **FileNameEditor** that could do what I need, or at least that is what is suggested here: https://stackoverflow.com/a/2373374/1248295. I didn't tried yet. – ElektroStudios May 28 '19 at 13:09
  • 1
    That Editor opens the standard file picker dialog (Open File) and lets you choose a file path/name. – Jimi May 28 '19 at 13:21

2 Answers2

3

There are builtin FileNameEditor and FolderNameEditor UI type editors which let you choose file name and folder name, for example:

using System.ComponentModel;
using System.Drawing.Design;
using System.Windows.Forms;
using System.Windows.Forms.Design;
public class MyClass
{
    [Editor(typeof(FileNameEditor), typeof(UITypeEditor))]
    public string FilePath { get; set; }

    [Editor(typeof(FolderNameEditor), typeof(UITypeEditor))]
    public string FolderPath { get; set; }
}

If you want to customize the FileNameEditor to show just txt files, you can override its InitializeDialog method:

public class MyFileNameEditor : FileNameEditor
{
    protected override void InitializeDialog(OpenFileDialog openFileDialog)
    {
        base.InitializeDialog(openFileDialog);
        openFileDialog.Filter = "text files (*.txt)|*.txt";
    }
}
Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
1

In my application, I have a property that takes a icon file path, another property that can take a file or folder, and other property that takes a folder path.

So, I had to write variations for each one of these properties...

The easiest one, and in case of you are satisfied with the FolderBrowserDialog appearance and limitations, then is to directly specify the System.Windows.Forms.Design.FolderNameEditor class in the EditorAttribute class. Otherwise, Ooki.Dialogs is a good open-source library as an alternative to get a modern-look dialog.

The second easiest one is the editor for selecting a icon file path:

''' <summary>
''' Provides a user interface for selecting a icon file name.
''' </summary>
''' <seealso cref="FileNameEditor"/>
Friend Class IconFileNameEditor : Inherits FileNameEditor

#Region " Constructors "

    ''' <summary>
    ''' Initializes a new instance of the <see cref="IconFileNameEditor"/> class.
    ''' </summary>
    Public Sub New()
        MyBase.New()
    End Sub

#End Region

#Region " Private Methods "

    ''' <summary>
    ''' Initializes the open file dialog when it is created.
    ''' </summary>
    ''' <param name="ofd">
    ''' The <see cref="OpenFileDialog"/> to use to select a file name.
    ''' </param>
    Protected Overrides Sub InitializeDialog(ByVal dlg As OpenFileDialog)
        MyBase.InitializeDialog(dlg)

        With dlg
            .Multiselect = False
            .RestoreDirectory = True
            .DereferenceLinks = True
            .Filter = "Icon Files (*.ico;*.icl;*.exe;*.dll)|*.ico;*.icl;*.exe;*.dll|Icons|*.ico|Libraries|*.dll|Programs|*.exe"
            .FilterIndex = 1
            .SupportMultiDottedExtensions = True
        End With
    End Sub

#End Region

End Class

For selecting a file path or folder path, and in search of something already done and open-source in order to avoid adding external dependancies to my project, I took a custom FileFolderDialog class provided in this article, and I managed to write the editor like this:

''' <summary>
''' Provides a user interface for selecting a file or folder name.
''' </summary>
''' <seealso cref="UITypeEditor"/>
Public Class FileOrFolderNameEditor : Inherits UITypeEditor

#Region " Constructors "

    ''' <summary>
    ''' Initializes a new instance of the <see cref="FileOrFolderNameEditor"/> class.
    ''' </summary>
    Public Sub New()
        MyBase.New()
    End Sub

#End Region

#Region " Public Methods"

    ''' <summary>
    ''' Gets the editor style used by the <see cref="UITypeEditor.EditValue(IServiceProvider, Object)"/> method.
    ''' </summary>
    ''' <param name="context">
    ''' An <see cref="ITypeDescriptorContext"/> that can be used to gain additional context information.
    ''' </param>
    ''' <returns>
    ''' A <see cref="UITypeEditorEditStyle"/> value that indicates the style of editor used 
    ''' by the <see cref="UITypeEditor.EditValue(IServiceProvider, Object)"/> method. 
    ''' <para></para>
    ''' If the <see cref="UITypeEditor"/> does not support this method, 
    ''' then <see cref="UITypeEditor.GetEditStyle"/> will return <see cref="UITypeEditorEditStyle.None"/>.
    ''' </returns>
    Public Overrides Function GetEditStyle(ByVal context As ITypeDescriptorContext) As UITypeEditorEditStyle
        Return UITypeEditorEditStyle.Modal
    End Function

    ''' <summary>
    ''' Edits the specified object's value using the editor style indicated by the <see cref="UITypeEditor.GetEditStyle"/> method.
    ''' </summary>
    ''' <param name="context">
    ''' An <see cref="ITypeDescriptorContext"/> that can be used to gain additional context information.
    ''' </param>
    ''' <param name="provider">
    ''' An <see cref="IServiceProvider"/> that this editor can use to obtain services.
    ''' </param>
    ''' <param name="value">
    ''' The object to edit.
    ''' </param>
    ''' <returns>
    ''' The new value of the object. 
    ''' <para></para>
    ''' If the value of the object has not changed, this should return the same object it was passed.
    ''' </returns>
    Public Overrides Function EditValue(ByVal context As ITypeDescriptorContext, ByVal provider As IServiceProvider, ByVal value As Object) As Object

        Using dlg As New OpenFileOrFolderDialog()
            If (dlg.ShowDialog = DialogResult.OK) Then
                Return dlg.SelectedPath
            End If
        End Using

        Return MyBase.EditValue(context, provider, value)

    End Function

#End Region

End Class

It was pretty easy at all.

Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
ElektroStudios
  • 19,105
  • 33
  • 200
  • 417