Gibt es eine "einfache" Möglichkeit, entweder eine Datei OR einen Ordner aus demselben Dialog auszuwählen?
In vielen Apps, die ich erstelle, kann ich sowohl Dateien als auch Ordner als Eingabe zulassen. Bislang habe ich immer einen Schalter zum Wechseln zwischen Datei- oder Ordnerauswahldialogen oder nur mit Drag & Drop-Funktionalität erstellt.
Da dies so eine grundlegende Sache zu sein scheint, würde ich mir vorstellen, dass dies schon vorher erstellt wurde, aber das Googeln führt nicht zu vielen Informationen. Es sieht also so aus, als müsste ich bei Null anfangen und einen benutzerdefinierten Auswahldialog erstellen, aber ich stelle keine Probleme vor, indem ich das Rad für eine solche triviale Aufgabe neu erfinde.
Jemand irgendwelche Tipps oder bestehende Lösungen?
Um die Benutzeroberfläche konsistent zu halten, wäre es schön, wenn der OpenFileDialog (oder der FolderBrowserDialog) erweitert werden könnte.
Technisch ist es möglich. Das von FolderBrowseDialog verwendete Shell-Dialogfeld kann Dateien und Ordner zurückgeben. Leider ist diese Funktion in .NET nicht verfügbar. Nicht einmal eine Reflexion kann das erforderliche Optionsflag setzen.
Damit dies funktioniert, müssen Sie SHBrowseForFolder () mit dem Flag BIF_BROWSEINCLUDEFILES in BROWSEINFO.ulFlags aktivieren (Wert = 0x4000). Das P/Invoke ist grobkörnig. Es ist am besten, den Code aus einer anderen Quelle oder der FolderBrowseDialog-Klasse selbst mit Hilfe von Reflector zu kopieren und einzufügen.
Basierend auf den obigen Tipps habe ich an der folgenden Stelle einen Funktionscode gefunden, der das Standarddialogfeld "Folder Browser" verwendet: http://topic.csdn.net/t/20020703/05/845468.html
Die Klasse für den erweiterten Ordnerbrowser-Dialog
Imports System
Imports System.Text
Imports System.Windows.Forms
Imports System.Runtime.InteropServices
Public Class DirectoryDialog
Public Structure BROWSEINFO
Public hWndOwner As IntPtr
Public pIDLRoot As Integer
Public pszDisplayName As String
Public lpszTitle As String
Public ulFlags As Integer
Public lpfnCallback As Integer
Public lParam As Integer
Public iImage As Integer
End Structure
Const MAX_PATH As Integer = 260
Public Enum BrowseForTypes As Integer
Computers = 4096
Directories = 1
FilesAndDirectories = 16384
FileSystemAncestors = 8
End Enum
Declare Function CoTaskMemFree Lib "ole32" Alias "CoTaskMemFree" (ByVal hMem As IntPtr) As Integer
Declare Function lstrcat Lib "kernel32" Alias "lstrcat" (ByVal lpString1 As String, ByVal lpString2 As String) As IntPtr
Declare Function SHBrowseForFolder Lib "Shell32" Alias "SHBrowseForFolder" (ByRef lpbi As BROWSEINFO) As IntPtr
Declare Function SHGetPathFromIDList Lib "Shell32" Alias "SHGetPathFromIDList" (ByVal pidList As IntPtr, ByVal lpBuffer As StringBuilder) As Integer
Protected Function RunDialog(ByVal hWndOwner As IntPtr) As Boolean
Dim udtBI As BROWSEINFO = New BROWSEINFO()
Dim lpIDList As IntPtr
Dim hTitle As GCHandle = GCHandle.Alloc(Title, GCHandleType.Pinned)
udtBI.hWndOwner = hWndOwner
udtBI.lpszTitle = Title
udtBI.ulFlags = BrowseFor
Dim buffer As StringBuilder = New StringBuilder(MAX_PATH)
buffer.Length = MAX_PATH
udtBI.pszDisplayName = buffer.ToString()
lpIDList = SHBrowseForFolder(udtBI)
hTitle.Free()
If lpIDList.ToInt64() <> 0 Then
If BrowseFor = BrowseForTypes.Computers Then
m_Selected = udtBI.pszDisplayName.Trim()
Else
Dim path As StringBuilder = New StringBuilder(MAX_PATH)
SHGetPathFromIDList(lpIDList, path)
m_Selected = path.ToString()
End If
CoTaskMemFree(lpIDList)
Else
Return False
End If
Return True
End Function
Public Function ShowDialog() As DialogResult
Return ShowDialog(Nothing)
End Function
Public Function ShowDialog(ByVal owner As IWin32Window) As DialogResult
Dim handle As IntPtr
If Not owner Is Nothing Then
handle = owner.Handle
Else
handle = IntPtr.Zero
End If
If RunDialog(handle) Then
Return DialogResult.OK
Else
Return DialogResult.Cancel
End If
End Function
Public Property Title() As String
Get
Return m_Title
End Get
Set(ByVal Value As String)
If Value Is DBNull.Value Then
Throw New ArgumentNullException()
End If
m_Title = Value
End Set
End Property
Public ReadOnly Property Selected() As String
Get
Return m_Selected
End Get
End Property
Public Property BrowseFor() As BrowseForTypes
Get
Return m_BrowseFor
End Get
Set(ByVal Value As BrowseForTypes)
m_BrowseFor = Value
End Set
End Property
Private m_BrowseFor As BrowseForTypes = BrowseForTypes.Directories
Private m_Title As String = ""
Private m_Selected As String = ""
Public Sub New()
End Sub
End Class
Der Code zum Implementieren des erweiterten Dialogs
Sub Button1Click(ByVal sender As Object, ByVal e As EventArgs)
Dim frmd As DirectoryDialog = New DirectoryDialog()
' frmd.BrowseFor = DirectoryDialog.BrowseForTypes.Directories
' frmd.BrowseFor = DirectoryDialog.BrowseForTypes.Computers
frmd.BrowseFor = DirectoryDialog.BrowseForTypes.FilesAndDirectories
frmd.Title = "Select a file or a folder"
If frmd.ShowDialog(Me) = DialogResult.OK Then
MsgBox(frmd.Selected)
End If
End Sub
Es wurde getan. Sie können FolderBrowserDialogEx - Verwenden, eine wiederverwendbare Ableitung des integrierten FolderBrowserDialogs. Hier können Sie einen Pfad eingeben, sogar einen UNC-Pfad. Sie können nach Ordnern oder Dateien + Ordnern suchen. Sie können damit nach Computern oder Druckern suchen. Basierend auf der eingebauten FBS, aber ... besser. Flexibler. Wenn Sie in der GUI auf einen Ordner klicken, wird der Pfad im Textfeld angezeigt. Wenn Sie einen Pfad eingeben, wird der Ordner aktiviert. Viele Optionen fehlen dem eingebauten Dialog.
Vollständiger Quellcode. Kostenlos. MS-Public Lizenz.
FolderBrowserDialogEx http://www.freeimagehosting.net/uploads/bfbab6cea5.png
Code, um es zu benutzen:
var dlg1 = new Ionic.Utils.FolderBrowserDialogEx();
dlg1.Description = "Select a folder to extract to:";
dlg1.ShowNewFolderButton = true;
dlg1.ShowEditBox = true;
//dlg1.NewStyle = false;
dlg1.SelectedPath = txtExtractDirectory.Text;
dlg1.ShowFullPathInEditBox = true;
dlg1.RootFolder = System.Environment.SpecialFolder.MyComputer;
// Show the FolderBrowserDialog.
DialogResult result = dlg1.ShowDialog();
if (result == DialogResult.OK)
{
txtExtractDirectory.Text = dlg1.SelectedPath;
}
Sie können den Standard-OpenFileDialog verwenden, um einen Ordner auszuwählen. Hier ist ein Artikel in CodeProject, in dem ein Weg aufgezeigt wurde ( http://www.codeproject.com/KB/dialog/OpenFileOrFolderDialog.aspx ).
http://www.pinvoke.net/default.aspx/Shell32.shbrowseforfolder
hier ist gerat link, wenn Sie in diesem Beispiel ändern
bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_SHAREABLE;
zum
bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_SHAREABLE | BIF_BROWSEINCLUDEFILES;
sie werden bekommen, was Sie wollen
AFAIK, es gibt nichts im .NET-Framework, das dies aus der Box heraus tut.
Die .NET-Dateidialoge stammen von CommonDialog :
Geerbte Klassen müssen Ausführen, um RunDialog durch Aufrufen von ShowDialog auszuführen, um ein bestimmtes allgemeines Dialogfeld Zu erstellen. Vererbte Klassen können HookProc überschreiben, um die Spezifische Dialogfeldhakenfunktion Zu implementieren.
Alle eingebauten Dialoge verwenden die Shell-APIs, die ihrer Aktion entsprechen, PrintDialog, OpenFileDialog, SaveFileDialog usw.
Sie müssen diese Funktionalität höchstwahrscheinlich manuell erstellen.
Wenn Sie nur bestimmte Dateitypen anzeigen möchten, kann Ihnen der folgende article (mit Quellcode in C #) helfen:
Außerdem werden die anderen Optionen erläutert, die zum "Anpassen" des Dialogfelds "FolderBrowser" verfügbar sind.
DieOokii-Dialogeimplementieren einen Ordnerbrowser-Dialog, der sowohl Dateien als auch Ordner als Eingabe zulässt und für Windows Forms und WPF verfügbar ist.
Ookii.Dialogs.Wpf
Ookii.Dialogs.WinForms
dadurch können Sie Ordner mithilfe von OpenFileDialog auswählen
openFileDialog1.CheckFileExists = false;
openFileDialog1.ValidateNames = false;