在Windows窗体中,我在PropertyGid
控件中表示一个自定义类,该控件具有各种字符串属性,如您在下一张图片中所注意到的:
问题在于,我对更改字符串属性值的当前行为并不完全满意。对于需要文件或目录路径的那些属性,例如“目标”或“工作目录”属性,我想知道是否有可能和可行的方法来实现将打开OpenFileDialog
的TypeConverter / Type描述符。单击属性网格中字段右侧的向下箭头。也就是说,通过OpenFileDialog
选择文件或文件夹,而不是直接在属性网格中写入路径,但是如果我愿意,仍然可以选择直接写入路径。
也许.NET Framework类库已经提供了我要的TypeConverter / TypeDescriptor?如果没有,这可能吗?以及如何开始这样做?
或者是否有其他想法可以打开OpenFileDialog
来更改PropertyGrid
控件中特定属性的值?
答案 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)
有内置的FileNameEditor
和FolderNameEditor
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";
}
}