打开OpenFileDialog来更改PropertyGrid控件中属性的值?

时间:2019-05-28 12:42:06

标签: c# .net vb.net winforms propertygrid

在Windows窗体中,我在PropertyGid控件中表示一个自定义类,该控件具有各种字符串属性,如您在下一张图片中所注意到的:

enter image description here

问题在于,我对更改字符串属性值的当前行为并不完全满意。对于需要文件或目录路径的那些属性,例如“目标”或“工作目录”属性,我想知道是否有可能和可行的方法来实现将打开OpenFileDialog的TypeConverter / Type描述符。单击属性网格中字段右侧的向下箭头。也就是说,通过OpenFileDialog选择文件或文件夹,而不是直接在属性网格中写入路径,但是如果我愿意,仍然可以选择直接写入路径。

也许.NET Framework类库已经提供了我要的TypeConverter / TypeDescriptor?如果没有,这可能吗?以及如何开始这样做?

或者是否有其他想法可以打开OpenFileDialog来更改PropertyGrid控件中特定属性的值?

2 个答案:

答案 0 :(得分:1)

在我的应用程序中,我有一个带有图标文件路径的属性,另一个可以带一个文件或文件夹的属性以及另一个带有文件夹路径的属性。

所以,我必须为这些属性中的每一个编写变体...

最简单的方法是,如果您对FolderBrowserDialog的外观和限制感到满意,那么可以直接在System.Windows.Forms.Design.FolderNameEditor类中指定EditorAttribute类。否则, Ooki.Dialogs 是一个很好的开源库,可以用来替代具有现代外观的对话框。

第二个最简单的方法是用于选择图标文件路径的编辑器:

''' <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

为了选择文件路径或文件夹路径,以及为了寻找已完成的事情和开源程序,以避免在项目中添加外部依赖,我选择了{{3}中提供的自定义FileFolderDialog类}文章,我设法这样编写编辑器:

''' <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

这很简单。

答案 1 :(得分:1)

有内置的FileNameEditorFolderNameEditor UI类型编辑器,可让您选择文件名和文件夹名,例如:

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; }
}

如果您要自定义FileNameEditor以仅显示txt文件,则可以覆盖其InitializeDialog方法:

public class MyFileNameEditor : FileNameEditor
{
    protected override void InitializeDialog(OpenFileDialog openFileDialog)
    {
        base.InitializeDialog(openFileDialog);
        openFileDialog.Filter = "text files (*.txt)|*.txt";
    }
}