OpenFileDialog1.Filter For A Specific File, Not File Type(s)

zunebuggy65

Active member
Joined
Oct 12, 2023
Messages
42
Programming Experience
3-5
I have a file that could be in various directories but the filename and extension itself is a known value. I would like the OpenFileDialog1 to allow the user to browse for it, but only that specific file.

I have tried
VB.NET:
OpenFileDialog1.Filter = "|filename.abc"
and it does work as you would expect, but the Filter that is displayed in the dialog dropdown right above the Open Cancel buttons doesn't look too pretty. Is there a better way to write the .Filter statement?

I'm pretty sure there is a way to do this because I have seen something similar in older versions of Windows. Maybe Windows XP, but it may have been a different type of file dialog or a custom one.

Thank you.
 
Filter is only for file extensions. You can prefill FileName too, it will not filter the files seen, but can give indication for what file user should select. FileOK event is cancellable and can be used validate and allow spesific filename(s) to be selected.
VB.NET:
e.Cancel = Path.GetFileNameWithoutExtension(OFD.FileName) <> "allowed name"
 
My code is below along with screenshots of the dialog showing only the desired file, when there are more files than that in the directory.

I do not know where to insert your code:
VB.NET:
e.Cancel = Path.GetFileNameWithoutExtension(OFD.FileName) <> "allowed name"
?

Also, in the screenshot below, the red arrow points to the part that looks messy to me. If it wasn't for this, I would totally use my filter.

~example1.png


VB.NET:
    Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
        OpenFileDialog1.Filter = "|CountyLedger.txt"
        OpenFileDialog1.InitialDirectory = Application.StartupPath
        OpenFileDialog1.FileName = "CountyLedger.txt"
        OpenFileDialog1.ShowDialog()
        TextBox3.Text = OpenFileDialog1.FileName
    End Sub

~example2.png


Thank you
 
Oh I see. I added

VB.NET:
    Private Sub OpenFileDialog1_FileOk(sender As Object, e As System.ComponentModel.CancelEventArgs) Handles OpenFileDialog1.FileOk
        e.Cancel = Path.GetFileNameWithoutExtension(OpenFileDialog1.FileName) <> "CountyLedger"
    End Sub
and that works great for ensuring the user picks the correct file.

Without a .Filter setting though, all other files in any directory are displayed. However if I set the OpenFileDialog1.Filter = "|CountyLedger.txt", then Only CountyLedger.txt is displayed but the box just above the Open and Cancel button doesn't look good. I was hoping there was a way to turn that box off. It usually is the File Type Selector dropdown, but in this case I do not need to have a File Type.

If not, I guess it's not that big of deal. I just wanted it to function properly AND to look pretty.

Thank you
 
That is not easy, it is a native OS dialog behind the scenes. It is possible, but very hacky using native methods.
Hiding the filter combobox also doesn't look good, disable it would be better in my opinion.
Code sample here is using Nuget package Vanara.PInvoke.User32 for all native declarations.
VB.NET:
Private Sub ShowFileDialog()
    Task.Run(AddressOf ModifyDialog)
    OFD.Title = "Select ledger file"
    If OFD.ShowDialog = DialogResult.OK Then
        Debug.WriteLine(OFD.FileName)
    End If
End Sub

Private Async Function ModifyDialog() As Task
    Await Task.Delay(500)
    Dim hw = User32.GetForegroundWindow
    If GetClassName(hw) = "#32770" AndAlso GetWinText(hw) = OFD.Title Then
        User32.EnumChildWindows(hw, AddressOf EnumWinCallback, 0)
    End If
End Function

Private Function EnumWinCallback(hw As HWND, lparam As IntPtr) As Boolean
    If GetClassName(hw) = "ComboBox" AndAlso GetWinText(hw) = " (test.pdf)" Then
        'User32.ShowWindow(hw, ShowWindowCommand.SW_HIDE) 'hide it
        User32.EnableWindow(hw, False) 'disable it
        Return False
    End If
    Return True
End Function

Private Function GetWinText(hw As HWND) As String
    Dim l = User32.GetWindowTextLength(hw) + 1
    Dim sb As New StringBuilder(l)
    User32.GetWindowText(hw, sb, l)
    Return sb.ToString
End Function

Private Function GetClassName(hw As HWND) As String
    Dim sb As New StringBuilder(256)
    User32.GetClassName(hw, sb, 256)
    Return sb.ToString
End Function
As you can see there is an initial timing issue, and some "magic strings" to make sure we have right window handles. The code to modify the dialog must run on secondary thread (Task.Run) and started before showing the dialog, therefore it must wait a little for the dialog window to be created (Task.Delay). Code then gets the window handle for current foreground window and validate it against dialog class name (#32770) and OFD.Title (set it to something that can be identified, if not Title is empty and dialog shows localized word "Open"). EnumChildWindows looks through all window handles within the dialog (each control is a "window"), and validate class name ("ComboBox") and displayed text (the filter, and actually has a space first). Once all this checks out the combobox can be hidden or disabled.
 
Back
Top