【问题标题】:How do I make a property of a custom control open a file dialog?如何使自定义控件的属性打开文件对话框?
【发布时间】:2020-05-08 11:16:44
【问题描述】:

我有一个自定义控件,其属性包含目标计算机上存在的文件位置的名称(完整路径)。

确切路径将根据目标电脑的类型而有所不同,并且通常在我将自定义控件添加到我的表单后立即设置,而我仍处于项目的设计模式,因此当我的应用程序运行时,它会拾取来自属性的文件名。

如果属性打开一个文件对话框让我浏览到该位置会很方便(类似于浏览图像和颜色属性时打开对话框的方式),但这在 Visual Basic 中似乎是不可能的。

在谷歌上搜索了几天后,我发现了几篇涉及其他编程语言主题的文章(参见下面的示例 sn-p),但我无法弄清楚如何使其适用于 Visual Basic。

这是我发现的一个 sn-p,其中提到了编辑器的使用,这可能是入门的线索。

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

希望有人能以正确的方式引导我。

【问题讨论】:

    标签: vb.net winforms custom-controls design-time uitypeeditor


    【解决方案1】:

    FileSelectorTypeEditor 可能是派生自FileNameEditorFolderNameEditor 的自定义类。

    您可以使用标准类来实现这两者,也可以使用自己的扩展默认类,正如您在找到的那些 C# 源代码中看到的那样。

    这里我使用了一个专门的FileNameEditor 类,命名为(有点缺乏想象力)SpecializedFileNameEditor 和标准的FolderNameEditorUITypeEditor 分配给一个类的两个属性.

    ImagePath 属性编辑器是 SpecializedFileNameEditor 对象,它使用 OpenFileDialog,其中预先选择了过滤器。它还覆盖 EditValue 方法,将关联属性(此处为 ImagePath)的当前值(如果有)设置为 OpenFileDialog 的 InitialDirectory。
    ImageFolder 属性编辑器是标准的FolderNameEditor,它会打开一个 FolderBrowserDialog。

    我还附加了一个ExpandableObjectConverter 类型转换器,因此您可以将这两个属性显示为PropertyGrid 中的可扩展属性选择器。

    您可以在此处查看示例:
    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
    

    【讨论】:

    • 感谢您对我最初的询问和解决问题的后续回答的投入!在测试您的解决方案时,我最初收到一个错误:'BC30002 Type 'FileNameEditor' is not defined。'。但是,Visual Studio 编辑器建议我添加来自 System.Design 的引用(位于 c:\Program Files (x86)\Reference Assemblies\Microsoft\Framwork\.NETFramework\v4.7.2\System.Design.dll 下)。一旦我这样做了,“System.Design”就会出现在解决方案资源管理器中我的 ControlLibrary 下的 References 中,一切都像一个魅力。感谢所有帮助和链接!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-29
    • 1970-01-01
    • 2011-12-11
    • 1970-01-01
    • 2019-10-24
    • 2012-04-29
    相关资源
    最近更新 更多