Hoe OpenFileDialog gebruiken om een ​​map te selecteren?

Hoe OpenFileDialogte gebruiken om mappen te selecteren?

Ik wilde het volgende project gebruiken: https://github.com/scottwis/OpenFileOrFolderDialog

Ik had echter één probleem. Het gebruikt de functie GetOpenFileNameen de structuur OPENFILENAME. En OPENFILENAMEheeft het lid met de naam templateID. Het is de identifier voor dialoogsjabloon. En het project bevat ook het bestand res1.rcen de sjabloondialoog init. Maar ik kon er niet achter komen hoe ik dit bestand aan mijn C#-project moest toevoegen.

Is er een betere manier om een ​​OpenFileDialogte gebruiken om mappen te selecteren?


Antwoord 1, autoriteit 100%

In principe heb je de FolderBrowserDialogklasse:

Vraagt ​​de gebruiker om een ​​map te selecteren. Deze klasse kan niet worden overgenomen.

Voorbeeld:

using(var fbd = new FolderBrowserDialog())
{
    DialogResult result = fbd.ShowDialog();
    if (result == DialogResult.OK && !string.IsNullOrWhiteSpace(fbd.SelectedPath))
    {
        string[] files = Directory.GetFiles(fbd.SelectedPath);
        System.Windows.Forms.MessageBox.Show("Files found: " + files.Length.ToString(), "Message");
    }
}

Als je in WPFwerkt, moet je de verwijzing naar System.Windows.Formstoevoegen.

je moet ook using System.IOtoevoegen voor de klasse Directory


Antwoord 2, autoriteit 83%

Als een opmerking voor toekomstige gebruikers die het gebruik van FolderBrowserDialogwillen vermijden, heeft Microsoft ooit een API uitgebracht met de naam WindowsAPICodePack met een handig dialoogvenster genaamd CommonOpenFileDialog, dat zou kunnen zijn ingesteld in een IsFolderPicker-modus. De API is verkrijgbaar bij Microsoft als een NuGet-pakket.

Dit is alles wat ik nodig had om de CommonOpenFileDialogte installeren en te gebruiken. (NuGet behandelde de afhankelijkheden)

Install-Package Microsoft.WindowsAPICodePack-Shell

Voor de include-regel:

using Microsoft.WindowsAPICodePack.Dialogs;

Gebruik:

CommonOpenFileDialog dialog = new CommonOpenFileDialog();
dialog.InitialDirectory = "C:\\Users";
dialog.IsFolderPicker = true;
if (dialog.ShowDialog() == CommonFileDialogResult.Ok)
{
    MessageBox.Show("You selected: " + dialog.FileName);
}

Antwoord 3, autoriteit 11%

Er is een hackachtige oplossing die OpenFileDialoggebruikt waarbij ValidateNamesen CheckFileExistsbeide zijn ingesteld op false en FileNameis een schijnwaarde gegeven om aan te geven dat een map is geselecteerd.

Ik zeg hacken omdat het voor gebruikers verwarrend is hoe ze een map moeten selecteren. Ze moeten in de gewenste map staan ​​en dan gewoon op Openen drukken terwijl de bestandsnaam “Mapselectie” zegt.

Dit is gebaseerd op Bestand selecteren of map uit hetzelfde dialoogvensterdoor Denis Stankovski.

OpenFileDialog folderBrowser = new OpenFileDialog();
// Set validate names and check file exists to false otherwise windows will
// not let you select "Folder Selection."
folderBrowser.ValidateNames = false;
folderBrowser.CheckFileExists = false;
folderBrowser.CheckPathExists = true;
// Always default to Folder Selection.
folderBrowser.FileName = "Folder Selection.";
if (folderBrowser.ShowDialog() == DialogResult.OK)
{
    string folderPath = Path.GetDirectoryName(folderBrowser.FileName);
    // ...
}

Antwoord 4, autoriteit 5%

Hier is een pure C#-versie, nuget-vrij, die zou moeten werken met alle versies van .NET (inclusief .NET Core, .NET 5, WPF, Winforms, enz.) en die Windows Vista (en hoger) gebruikt IFileDialog-interface met de FOS_PICKFOLDERSopties dus het heeft de mooie mapkiezer Windows standaard UI .

Ik heb ook WPF’s Windowondersteuning toegevoegd, maar dit is optioneel, de WPF-gemarkeerde regels kunnen gewoon worden verwijderd.

gebruik:

var dlg = new FolderPicker();
dlg.InputPath = @"c:\windows\system32";
if (dlg.ShowDialog() == true)
{
    MessageBox.Show(dlg.ResultPath);
}

code:

   using System;
    using System.Diagnostics;
    using System.Runtime.InteropServices;
    using System.Runtime.InteropServices.ComTypes;
    using System.Windows; // for WPF support
    using System.Windows.Interop;  // for WPF support
    public class FolderPicker
    {
        public virtual string ResultPath { get; protected set; }
        public virtual string ResultName { get; protected set; }
        public virtual string InputPath { get; set; }
        public virtual bool ForceFileSystem { get; set; }
        public virtual string Title { get; set; }
        public virtual string OkButtonLabel { get; set; }
        public virtual string FileNameLabel { get; set; }
        protected virtual int SetOptions(int options)
        {
            if (ForceFileSystem)
            {
                options |= (int)FOS.FOS_FORCEFILESYSTEM;
            }
            return options;
        }
        // for WPF support
        public bool? ShowDialog(Window owner = null, bool throwOnError = false)
        {
            owner ??= Application.Current.MainWindow;
            return ShowDialog(owner != null ? new WindowInteropHelper(owner).Handle : IntPtr.Zero, throwOnError);
        }
        // for all .NET
        public virtual bool? ShowDialog(IntPtr owner, bool throwOnError = false)
        {
            var dialog = (IFileOpenDialog)new FileOpenDialog();
            if (!string.IsNullOrEmpty(InputPath))
            {
                if (CheckHr(SHCreateItemFromParsingName(InputPath, null, typeof(IShellItem).GUID, out var item), throwOnError) != 0)
                    return null;
                dialog.SetFolder(item);
            }
            var options = FOS.FOS_PICKFOLDERS;
            options = (FOS)SetOptions((int)options);
            dialog.SetOptions(options);
            if (Title != null)
            {
                dialog.SetTitle(Title);
            }
            if (OkButtonLabel != null)
            {
                dialog.SetOkButtonLabel(OkButtonLabel);
            }
            if (FileNameLabel != null)
            {
                dialog.SetFileName(FileNameLabel);
            }
            if (owner == IntPtr.Zero)
            {
                owner = Process.GetCurrentProcess().MainWindowHandle;
                if (owner == IntPtr.Zero)
                {
                    owner = GetDesktopWindow();
                }
            }
            var hr = dialog.Show(owner);
            if (hr == ERROR_CANCELLED)
                return null;
            if (CheckHr(hr, throwOnError) != 0)
                return null;
            if (CheckHr(dialog.GetResult(out var result), throwOnError) != 0)
                return null;
            if (CheckHr(result.GetDisplayName(SIGDN.SIGDN_DESKTOPABSOLUTEPARSING, out var path), throwOnError) != 0)
                return null;
            ResultPath = path;
            if (CheckHr(result.GetDisplayName(SIGDN.SIGDN_DESKTOPABSOLUTEEDITING, out path), false) == 0)
            {
                ResultName = path;
            }
            return true;
        }
        private static int CheckHr(int hr, bool throwOnError)
        {
            if (hr != 0)
            {
                if (throwOnError)
                    Marshal.ThrowExceptionForHR(hr);
            }
            return hr;
        }
        [DllImport("shell32")]
        private static extern int SHCreateItemFromParsingName([MarshalAs(UnmanagedType.LPWStr)] string pszPath, IBindCtx pbc, [MarshalAs(UnmanagedType.LPStruct)] Guid riid, out IShellItem ppv);
        [DllImport("user32")]
        private static extern IntPtr GetDesktopWindow();
#pragma warning disable IDE1006 // Naming Styles
        private const int ERROR_CANCELLED = unchecked((int)0x800704C7);
#pragma warning restore IDE1006 // Naming Styles
        [ComImport, Guid("DC1C5A9C-E88A-4dde-A5A1-60F82A20AEF7")] // CLSID_FileOpenDialog
        private class FileOpenDialog
        {
        }
        [ComImport, Guid("42f85136-db7e-439c-85f1-e4075d135fc8"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        private interface IFileOpenDialog
        {
            [PreserveSig] int Show(IntPtr parent); // IModalWindow
            [PreserveSig] int SetFileTypes();  // not fully defined
            [PreserveSig] int SetFileTypeIndex(int iFileType);
            [PreserveSig] int GetFileTypeIndex(out int piFileType);
            [PreserveSig] int Advise(); // not fully defined
            [PreserveSig] int Unadvise();
            [PreserveSig] int SetOptions(FOS fos);
            [PreserveSig] int GetOptions(out FOS pfos);
            [PreserveSig] int SetDefaultFolder(IShellItem psi);
            [PreserveSig] int SetFolder(IShellItem psi);
            [PreserveSig] int GetFolder(out IShellItem ppsi);
            [PreserveSig] int GetCurrentSelection(out IShellItem ppsi);
            [PreserveSig] int SetFileName([MarshalAs(UnmanagedType.LPWStr)] string pszName);
            [PreserveSig] int GetFileName([MarshalAs(UnmanagedType.LPWStr)] out string pszName);
            [PreserveSig] int SetTitle([MarshalAs(UnmanagedType.LPWStr)] string pszTitle);
            [PreserveSig] int SetOkButtonLabel([MarshalAs(UnmanagedType.LPWStr)] string pszText);
            [PreserveSig] int SetFileNameLabel([MarshalAs(UnmanagedType.LPWStr)] string pszLabel);
            [PreserveSig] int GetResult(out IShellItem ppsi);
            [PreserveSig] int AddPlace(IShellItem psi, int alignment);
            [PreserveSig] int SetDefaultExtension([MarshalAs(UnmanagedType.LPWStr)] string pszDefaultExtension);
            [PreserveSig] int Close(int hr);
            [PreserveSig] int SetClientGuid();  // not fully defined
            [PreserveSig] int ClearClientData();
            [PreserveSig] int SetFilter([MarshalAs(UnmanagedType.IUnknown)] object pFilter);
            [PreserveSig] int GetResults([MarshalAs(UnmanagedType.IUnknown)] out object ppenum);
            [PreserveSig] int GetSelectedItems([MarshalAs(UnmanagedType.IUnknown)] out object ppsai);
        }
        [ComImport, Guid("43826D1E-E718-42EE-BC55-A1E261C37BFE"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        private interface IShellItem
        {
            [PreserveSig] int BindToHandler(); // not fully defined
            [PreserveSig] int GetParent(); // not fully defined
            [PreserveSig] int GetDisplayName(SIGDN sigdnName, [MarshalAs(UnmanagedType.LPWStr)] out string ppszName);
            [PreserveSig] int GetAttributes();  // not fully defined
            [PreserveSig] int Compare();  // not fully defined
        }
        #pragma warning disable CA1712 // Do not prefix enum values with type name
        private enum SIGDN : uint
        {
            SIGDN_DESKTOPABSOLUTEEDITING = 0x8004c000,
            SIGDN_DESKTOPABSOLUTEPARSING = 0x80028000,
            SIGDN_FILESYSPATH = 0x80058000,
            SIGDN_NORMALDISPLAY = 0,
            SIGDN_PARENTRELATIVE = 0x80080001,
            SIGDN_PARENTRELATIVEEDITING = 0x80031001,
            SIGDN_PARENTRELATIVEFORADDRESSBAR = 0x8007c001,
            SIGDN_PARENTRELATIVEPARSING = 0x80018001,
            SIGDN_URL = 0x80068000
        }
        [Flags]
        private enum FOS
        {
            FOS_OVERWRITEPROMPT = 0x2,
            FOS_STRICTFILETYPES = 0x4,
            FOS_NOCHANGEDIR = 0x8,
            FOS_PICKFOLDERS = 0x20,
            FOS_FORCEFILESYSTEM = 0x40,
            FOS_ALLNONSTORAGEITEMS = 0x80,
            FOS_NOVALIDATE = 0x100,
            FOS_ALLOWMULTISELECT = 0x200,
            FOS_PATHMUSTEXIST = 0x800,
            FOS_FILEMUSTEXIST = 0x1000,
            FOS_CREATEPROMPT = 0x2000,
            FOS_SHAREAWARE = 0x4000,
            FOS_NOREADONLYRETURN = 0x8000,
            FOS_NOTESTFILECREATE = 0x10000,
            FOS_HIDEMRUPLACES = 0x20000,
            FOS_HIDEPINNEDPLACES = 0x40000,
            FOS_NODEREFERENCELINKS = 0x100000,
            FOS_OKBUTTONNEEDSINTERACTION = 0x200000,
            FOS_DONTADDTORECENT = 0x2000000,
            FOS_FORCESHOWHIDDEN = 0x10000000,
            FOS_DEFAULTNOMINIMODE = 0x20000000,
            FOS_FORCEPREVIEWPANEON = 0x40000000,
            FOS_SUPPORTSTREAMABLEITEMS = unchecked((int)0x80000000)
        }
        #pragma warning restore CA1712 // Do not prefix enum values with type name
    }

Resultaat:


Antwoord 5, Autoriteit 3%

Vreemde dat zoveel antwoorden / stemmen, maar niemand de volgende code als antwoord toevoegen:

using (var opnDlg = new OpenFileDialog()) //ANY dialog
{ 
    //opnDlg.Filter = "Png Files (*.png)|*.png";
    //opnDlg.Filter = "Excel Files (*.xls, *.xlsx)|*.xls;*.xlsx|CSV Files (*.csv)|*.csv"
    if (opnDlg.ShowDialog() == DialogResult.OK)
    {
        //opnDlg.SelectedPath -- your result
    }
}

Antwoord 6, Autoriteit 3%

klinkt aan mij alsof je net na de .


Antwoord 7, Autoriteit 2%

Hier is een andere oplossing, die alle bron beschikbaar heeft in een enkelvoudig, eenvoudig zip-bestand.

Het presenteert de OpenFileialog met extra Windows-vlaggen die het laten werken zoals het dialoogvenster Windows 7+ mappen.

Per de website, het is Public Domain: “Er is geen licentie als zodanig dat je vrij bent om te nemen en te doen met de code wat je wilt.”

archive.org links:


Antwoord 8

Bekijk de oookii-dialoogvensters bibliotheken met een implementatie van respectievelijk een mapbrowser-dialoogvenster voor Windows-formulieren en WPF.

ookii.dialogs.winforms

https://github.com/augustoProiete/ookii-dialogs-winforms


ookii.dialogs.wpf

https://github.com/augustoProiete/ookii-dialogs-wpf


Antwoord 9

Dit zou de meest voor de hand liggende en ongecompliceerde manier moeten zijn

using (var dialog = new System.Windows.Forms.FolderBrowserDialog())
{
   System.Windows.Forms.DialogResult result = dialog.ShowDialog();
   if(result == System.Windows.Forms.DialogResult.OK)
   {
      selectedFolder = dialog.SelectedPath;
   }
}

Other episodes