【问题标题】:Open a OpenFileDialog to change the value of a property in a PropertyGrid control?打开 OpenFileDialog 以更改 PropertyGrid 控件中的属性值?
【发布时间】:2019-05-28 12:42:06
【问题描述】:

在 Windows 窗体中,我在 PropertyGid 控件中表示一个自定义类,它具有各种字符串属性,如下图所示:

问题是我对当前更改字符串属性值的行为并不完全满意。对于那些需要文件或目录路径的属性,例如“目标”或“工作目录”属性,我想知道实现一个 TypeConverter / Type Descriptor 是否可行且可行,它会在单击时打开 OpenFileDialog在属性网格中字段右侧的向下箭头中。即通过OpenFileDialog选择文件或文件夹,而不是直接在属性网格中写入路径,但如果我想这样做仍然让选项直接写入路径。

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

或者任何其他能够打开OpenFileDialog 以更改PropertyGrid 控件中特定属性的值的想法?

【问题讨论】:

  • 框架对 IShellLink 一无所知。创建模态 UITypeEditor 以自定义值编辑。
  • @Hans Passant 感谢您的评论。我将从以下代码示例开始练习:docs.microsoft.com/en-us/dotnet/api/system.drawing.design.uitypeeditor?view=netframework-4.8,但我会指出这些属性是字符串数据-类型。
  • 显然有一个类名为 FileNameEditor 的内置 UITypeEditor 可以做我需要的,或者至少这是这里建议的:stackoverflow.com/a/2373374/1248295。我还没试过。
  • 该编辑器打开标准文件选择器对话框(打开文件)并让您选择文件路径/名称。

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


【解决方案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";
    }
}

【讨论】:

    【解决方案2】:

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

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

    最简单的一种,如果你对FolderBrowserDialog的外观和限制感到满意,那就直接在EditorAttribute类中指定System.Windows.Forms.Design.FolderNameEditor类。否则,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
    

    为了选择文件路径或文件夹路径,并寻找已经完成的开源项目以避免向我的项目添加外部依赖项,我采用了 this 文章中提供的自定义 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
    

    这很容易。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-12
      • 2010-12-05
      • 1970-01-01
      相关资源
      最近更新 更多