Visual Basic的 Windows打开文件对话框有时不会显示文件夹窗格
这段继承自已有代码的代码中,有一个用于显示 System.Windows.Forms.OpenFileDialog 控件的方法,在从主窗体调用时工作正常。但从任意子窗体调用时,左边的文件夹面板却是空的。
代码据我所知相当简单。
Public Function ShowFilenameFromDialogEx(ByVal fOwner As Form, ByVal strFilename As String, ByVal strExt As String) As String
Dim bReturn As Boolean
Dim OD As New System.Windows.Forms.OpenFileDialog
Dim F As String
Dim strFilter As String
strFilter = UCase(strExt) & " files (*." & strExt & ")|" & "*." & strExt & "|All Files (*.*)|*.*"
F = ""
' reset
OD.Filter = strFilter
OD.FilterIndex = 1
OD.Tag = "FileBrowser"
OD.DefaultExt = strExt
If strFilename <> "" Then
OD.FileName = ExtractFileName(strFilename) 'helper function to get just filename
OD.InitialDirectory = ExtractFilePath(strFilename) 'helper function to get file path
Else
OD.FileName = ""
OD.InitialDirectory = ""
End If
bReturn = OD.ShowDialog() = DialogResult.OK
If bReturn Then
F = OD.FileName
End If
OD = Nothing
ShowFilenameFromDialogEx = F
End Function
ShowFilenameFromDialogEx(Me, "D:\Temp\test\test.txt", "txt")
使用Visual Studio 2015和 VB代码。
从主窗体,我可以无问题地反复调用它。一切看起来都很正常。
从任意子窗体调用时,左侧应该出现文件夹的区域总是空白。
有人遇到过类似的情况吗?有哪些需要排查的地方?
编辑:
刚在主窗体和其中一个子窗体上各添加了一个简单按钮,并执行了以下操作。从主窗体调用时会显示文件夹列表,而在任何子窗体上都不会显示。
Dim OD As New System.Windows.Forms.OpenFileDialog
OD.ShowDialog(Me)
构建成的可执行文件在其他计算机上测试,仍然是同样的问题。是库或引用方面的原因吗?
解决方案
如果你在想对话框中空白区域叫什么,这里叫做“导航窗格”。
这也是那种我看不出有什么明显原因会导致这种行为的情形,但确实有一堆代码可以清理。比如:
-
我不会让这个方法(以及其中调用的方法)成为实例成员。相反,它们应该是静态(在VB中称为Shared)成员。
-
你把
fOwner定义为一个参数,但从未使用它。你本可以在ShowDialog调用中传入它,但说实话,我会让.NET自己处理,直接把该参数删掉。 -
你在定义OpenFileDialog时没有正确处置。该类实现了IDisposable,处理的最佳方式是使用Using语句,而不必担心把实例设为空。
-
为了不过分挑剔,但值得一提的是,UCase是一个遗留的做法。直接使用ToUpper或 ToUpperInvariant。为了可读性,你还可以使用字符串插值,这在Visual Studio 2015中是被支持的。
-
没有理由设置
F的值,因为字符串的默认值本来就是空字符串,虽然如果你确实想显式设置,最好把它移到变量创建的位置。 -
同样,OpenFileDialog的 FileName和 InitialDirectory属性的默认值也是空字符串。你的else语句完全没有必要。
-
还有一些内置方法可以实现你在ExtractFileName和 ExtractFilePath方法中大概做的事情。
-
与其检查filename参数是否为空字符串,不如改为检查它是否为null或仅包含空白字符。例如,如果有人传入一个空值到底会怎样?
-
将
ShowFilenameFromDialogEx设为返回值在VB.NET中是一种非常过时的做法。更好的做法是直接使用return关键字。
话虽如此,请尝试对该方法进行重写,看看是否能解决你的问题。虽然我不能百分之百确定一定能解决,但有时对代码进行重构、采用更好的做法,确实能够修复一些怪异的边界情况。
Public Shared Function ShowFilenameFromDialogEx(filename As String, extension As String) As String
' define the default value to return
Dim selectedFilename As String = String.Empty
' set the dialog filter
Dim filter As String = $"{extension.ToUpperInvariant()} files (*.{extension})|*.{extension}|All Files (*.*)|*.*"
' create a new instance of a dialog
Using ofd As New OpenFileDialog()
' set the default properties
With ofd
.DefaultExt = extension
.Filter = filter
.FilterIndex = 1
.Tag = "FileBrowser"
End With
' set the default properties dependent on filename
If (Not String.IsNullOrWhitespace(filename)) Then
ofd.FileName = System.IO.Path.GetFileName(filename)
ofd.InitialDirectory = System.IO.Path.GetDirectoryName(filename)
End If
' check if the user clicked on Ok
If (ofd.ShowDialog() = DialogResult.Ok) Then
' set the returned result to the result of the dialog
selectedFilename = ofd.FileName
End If
End Using
' return the default value or the selected filename
Return selectedFilename
End Function
由于方法的签名已改为静态方法,因此调用它时不再需要Form的实例。例如,如果该方法位于FormMain类中,你只需调用:
FormMain.ShowFilenameFromDialogEx("...", "...")
