Seleziona un file o una cartella dalla stessa finestra di dialogo in .NET

Esiste un modo “facile” per selezionare un file O una cartella dalla stessa finestra di dialogo?

In molte app che creo, autorizzo sia i file che le cartelle come input. Fino ad ora finivo sempre per creare un interruttore per alternare le windows di selezione dei file o delle cartelle o solo con la funzionalità di trascinamento della selezione.

Dal momento che sembra una cosa così elementare immagino che questo sia stato creato prima, ma googling non risulta in molte informazioni. Quindi sembra che dovrei ricominciare da zero e creare una finestra di selezione personalizzata, ma piuttosto non introdurre alcun problema reinventando la ruota per un’operazione così banale.

Qualcuno qualche consiglio o soluzioni esistenti?

Per mantenere l’interfaccia utente coerente sarebbe bello se fosse ansible estendere OpenFileDialog (o FolderBrowserDialog).

    Tecnicamente, è ansible. La finestra di dialogo della shell utilizzata da FolderBrowseDialog ha la capacità di restituire sia i file che le cartelle. Sfortunatamente, questa funzionalità non è esposta in .NET. Neanche il riflesso può colpire il flag opzionale richiesto.

    Per farlo funzionare, devi P / Invoke SHBrowseForFolder () con il flag BIF_BROWSEINCLUDEFILES triggersto in BROWSEINFO.ulFlags (valore = 0x4000). P / Invoke è grintoso, è meglio copiare e incollare il codice da un’altra fonte o la class FolderBrowseDialog stessa con l’aiuto di Reflector.

    Sulla base dei suggerimenti di cui sopra ho trovato un codice funzionante che utilizza la finestra di dialogo Browser cartella standard nel seguente percorso: http://topic.csdn.net/t/20020703/05/845468.html

    La class per la finestra di dialogo Browser cartella estesa

    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 

    Il codice per implementare la finestra di dialogo estesa

     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 

    È stato fatto. Puoi utilizzare FolderBrowserDialogEx , una derivata riutilizzabile del FolderBrowserDialog incorporato. Questo ti permette di digitare un percorso, anche un percorso UNC. È ansible cercare cartelle o file + cartelle. Puoi cercare computer o stampanti con esso. Basato sul FBD integrato, ma … meglio. Più flessibile. Se si fa clic su una cartella nella GUI, il percorso viene visualizzato nella casella di testo. Se si digita un percorso, la cartella viene triggersta. Un sacco di opzioni manca la finestra di dialogo integrata.

    Codice sorgente completo Gratuito. Licenza pubblica MS.

    FolderBrowserDialogEx http://sofit.miximages.com/c%23/www.freeimagehosting.net

    Codice per usarlo:

      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; } 

    È ansible utilizzare OpenFileDialog standard per selezionare una cartella. Ecco un articolo in CodeProject che ha dimostrato un modo per farlo ( http://www.codeproject.com/KB/dialog/OpenFileOrFolderDialog.aspx ).

    AFAIK, non c’è nulla nel framework .NET che faccia questo fuori dalla scatola.

    Le windows di dialogo dei file .NET derivano da CommonDialog :

    Le classi ereditate sono necessarie per implementare RunDialog richiamando ShowDialog per creare una finestra di dialogo comune specifica. Le classi ereditate possono ignorare HookProc per implementare la funzionalità di hook della finestra di dialogo specifica.

    Tutte le windows di dialogo incorporate utilizzano le API della shell che corrispondono alla loro azione, PrintDialog, OpenFileDialog, SaveFileDialog, ecc …

    Molto probabilmente dovresti creare manualmente questa funzionalità.

    http://www.pinvoke.net/default.aspx/shell32.shbrowseforfolder

    qui c’è il collegamento gerat se cambi in questo esempio

      bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_SHAREABLE; 

    per

      bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_SHAREABLE | BIF_BROWSEINCLUDEFILES; 

    otterrai quello che vuoi

    Se desideri visualizzare solo tipi di file specifici, il seguente articolo (con codice sorgente in C #) può aiutarti a:

    http://www.codeproject.com/KB/shell/csdoesshell1.aspx?fid=14137&df=90&mpp=25&noise=3&sort=Position&view=Quick&fr=26

    Spiega anche le altre opzioni disponibili per “personalizzare” la finestra di dialogo FolderBrowser,

    questo ti permetterà di selezionare le cartelle usando OpenFileDialog

      openFileDialog1.CheckFileExists = false; openFileDialog1.ValidateNames = false;