Jak skonfigurować OpenFileDialog do wybierania folderów?

250

W VS .NET, gdy wybierasz folder dla projektu, wyświetlane jest okno dialogowe wyglądające jak OpenFileDialog lub SaveFileDialog, ale skonfigurowane tak, aby akceptowało tylko foldery. Odkąd to widziałem, chciałem wiedzieć, jak to się robi. Jestem świadomy FolderBrowserDialog, ale tak naprawdę nigdy nie podobało mi się to okno dialogowe. Zaczyna się za mały i nie pozwala mi skorzystać z możliwości wpisania ścieżki.

Jestem już prawie pewien, że nie ma sposobu, aby to zrobić z .NET, ale jestem równie ciekawy, jak to zrobić z niezarządzanego kodu. Poza całkowitym ponownym wdrożeniem okna dialogowego od zera, jak zmodyfikować okno dialogowe, aby uzyskać takie zachowanie?

Chciałbym również powtórzyć, że znam FolderBrowserDialog, ale czasami nie lubię go używać, oprócz tego, że jestem naprawdę ciekawy, jak skonfigurować okno dialogowe w ten sposób. Mówienie mi, żebym po prostu użył FolderBrowserDialog, pomaga mi zachować spójność interfejsu użytkownika, ale nie zaspokaja mojej ciekawości, więc nie będzie liczony jako odpowiedź.

Nie jest to również kwestia specyficzna dla systemu Vista; Widzę to okno dialogowe od VS .NET 2003, więc jest możliwe do wykonania w Win2k i WinXP. Jest to w mniejszym stopniu pytanie „chcę wiedzieć, jak to zrobić poprawnie”, a bardziej „byłem ciekaw tego, odkąd po raz pierwszy chciałem to zrobić w VS 2003”. Rozumiem, że okno dialogowe plików Visty ma taką opcję, ale działa w XP, więc wiem, że zrobili coś, aby to zadziałało. Odpowiedzi specyficzne dla systemu Vista nie są odpowiedziami, ponieważ system Vista nie istnieje w kontekście pytań.

Aktualizacja: Jestem przyjmując odpowiedź Scott Wiśniewski, ponieważ chodzi o próbki roboczej, ale myślę, że Serge zasługuje na uznanie za wskazując na dostosowanie dialogowym (który jest wprawdzie paskudny z .NET, ale nie pracę) i Mark Ransom na zastanawianie się, że MS prawdopodobnie utworzył niestandardowe okno dialogowe dla tego zadania.

OwenP
źródło
7
tylko proste rozwiązanie z codeproject codeproject.com/Articles/44914/… [Kluczem do uzyskania przez OpenFileDialog wyboru zarówno plików, jak i folderów jest ustawienie właściwości ValidateNames i CheckFileExists na wartość false (dialog.ValidateNames = false; dialog.CheckFileExists = false) i ustaw FileName na jakieś specjalne słowo kluczowe, aby upewnić się, że foldery zostaną wybrane (dialog.FileName = "Wybór folderu";).]
Riju
3
Prześlij to jako odpowiedź, to zadziałało w moim projekcie.
CigarDoug
@ Riju dialog.FileName = "Folder Selection"ma być dialog.FileName = "Folder Selection."z końcowym okresem? w każdym razie nie mogę sprawić, aby działał w PowerShell po drugim kliknięciu przycisku „Otwórz”. Ciągle mówi, że plik nie został znaleziony, mimo że CheckFileExists jest podobno fałszywy
ComradeJoecool
nvm, w ustawieniach powershell dialog.CheckFileExists = 0zamiast false rozwiązał mój problem
ComradeJoecool
Czy próbowałeś Ookii Dialogs dla WPF ?
C. Augusto Proiete,

Odpowiedzi:

57

Mam okno dialogowe, które napisałem, o nazwie Okno dialogowe OpenFileOrFolder, które pozwala otworzyć folder lub plik.

Jeśli ustawisz wartość AcceptFiles na false, wówczas działa tylko w trybie akceptowania folderów.

Możesz pobrać źródło z GitHub tutaj

Scott Wiśniewski
źródło
4
Bardzo interesujące i zdecydowanie tak skomplikowane, jak się spodziewałem. Czy jest jakaś szansa na opatrzenie go adnotacjami i wskazanie, co robi? To wraz z innymi komentarzami prowadzi mnie do przekonania, że ​​stwardnienie rozsiane prawdopodobnie właśnie rzuciło własny dialog.
OwenP,
1
Podczas próby zbudowania rozwiązania pojawia się następujący błąd ... niestety c ++ nie jest jedną z moich mocnych stron ... Błąd 1 nie może otworzyć pliku „afxres.h”.
Ignacio Soler Garcia
1
@SoMoS i inne z tym samym problemem: w pliku WindowsFormsApplication1.csproj edytuj linię 100, aby pasowała do twojej konfiguracji. W moim przypadku musiałem zmienić „9.0” na „10.0” (dwa razy) i usunąć „(x86)” (dwa razy).
RenniePet
2
Pobrałem kod (zip) i znalazłem plik .h (C) i skompilowałem z błędem, takim jak nie można otworzyć pliku dołączania „sal.h”.
Lei Yang
2
To rozwiązanie nie działa również na VS2010 i VS2017!
AleX_
49

Możesz użyć FolderBrowserDialogEx - wielokrotnego użytku pochodnej wbudowanej FolderBrowserDialog. Ten pozwala na wpisanie ścieżki, nawet ścieżki UNC. Za jego pomocą możesz także wyszukiwać komputery lub drukarki. Działa tak jak wbudowany FBD, ale ... lepiej.

(EDYCJA: Powinienem zauważyć, że to okno dialogowe można ustawić, aby wybrać pliki lub foldery.)

Pełny kod źródłowy (jeden krótki moduł C #). Wolny. Licencja MS-Public.

Kod, aby go użyć:

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;
}
Cheeso
źródło
7
Przepraszam, jeśli się obraziłem, frustrujące jest zadawanie pytań i pisanie: „Chcę tego konkretnego, a nie innych rzeczy” i niech ludzie chętnie zasugerują to, o co nie prosili. Chciałem okna dialogowego przeglądarki plików, a nie okna przeglądarki folderów.
OwenP,
15
Sposób, w jaki pytanie jest sformułowane, wydaje mi się, że prosi o okno dialogowe wyboru folderu - czy tak nie jest? W każdym razie właśnie tego szukałem +1
Tim
Zdecydowanie najlepsza jak dotąd odpowiedź
Wasil Popow
1
Nie zmienia to faktu, że odpowiedź wciąż jest odpowiedzią tylko na link. Pokazanie, jak korzystać z kodu hostowanego w zasobach zewnętrznych, przestaje być przydatne, gdy również ten link staje się tymczasowo lub trwale niedostępny. Reguły istnieją z jakiegoś powodu, a ten wkład jest sprzeczny z tymi zasadami.
IInspectable
1
Spojrzałem na odpowiedź i najwyraźniej nie odnosi się ona do zasobu zewnętrznego. Zatem „każda inna odpowiedź” jest wyraźnie błędna. Jeśli czujesz, że reaguję przesadnie, być może powinieneś poruszyć problem w meta, aby omówić zasady. Nie będę Po prostu je zastosuję.
IInspectable
48

Istnieje pakiet kodów Windows API. Ma wiele rzeczy związanych z powłoką, w tym CommonOpenFileDialogklasę (w Microsoft.WindowsAPICodePack.Dialogsprzestrzeni nazw). To idealne rozwiązanie - zwykle otwarte okno dialogowe z wyświetlanymi tylko folderami.

Oto przykład, jak z niego korzystać:

CommonOpenFileDialog cofd = new CommonOpenFileDialog();
cofd.IsFolderPicker = true;
cofd.ShowDialog();

Niestety Microsoft nie wysyła już tego pakietu, ale kilka osób nieoficjalnie przesłało pliki binarne do NuGet. Jeden przykład można znaleźć tutaj . Ten pakiet jest przeznaczony tylko dla powłoki. W razie potrzeby ten sam użytkownik ma kilka innych pakietów, które oferują więcej funkcji obecnych w oryginalnym pakiecie.

Ken Wayne Vander Linde
źródło
1
Nie wiedziałem, że jest to pakiet Windows API Code Pack - dziękuję za zwrócenie na to uwagi.
Patrick Klug,
10
Klasa CommonOpenFileDialog istnieje tylko w systemie Windows Vista lub nowszym, więc wyrzuci wyjątek na starsze systemy operacyjne
Rachel
1
Czy możesz powiedzieć, jak odwoływać się do pakietu Windows API Code Pack?
Jeff
1
Galeria Archiwum została wycofana. , a przynajmniej tak mówi link. Czy to może być nowe miejsce?
Domyślnie
3
Nawiasem mówiąc, klasa CommonOpenFileDialog znajduje się w przestrzeni nazw Microsoft.WindowsAPICodePack.Dialogs (zajęło mi to trochę czasu, aby ją znaleźć).
morgb
35

Ookii.Dialogs pakiet zawiera zarządzanej otoki wokół nowego stylu (Vista) okna przeglądarki folderu. Zniszcza się również z wdziękiem na starszych systemach operacyjnych.

Christian Klauser
źródło
2
Fajnie, to licencjonowane w stylu BSD oprogramowanie typu open source!
Roman Starkov
7
jedynym problemem jest to, że nie pozwolę używać profilu klienta .NET Framework jako celu.
Kugel
2
Bardzo fajne rozwiązanie. To jest moim zdaniem najlepsza odpowiedź. Dokładnie tego, czego szukałem od 3 lat.
Samuel
1
Kolejny problem z tym rozwiązaniem: nie pozwala użytkownikowi wkleić nieistniejącej ścieżki. Drobny, względnie, ale szkoda.
Roman Starkov
1
Najlepsza praktyczna odpowiedź dla tych, którzy chcą OpenFileDialogdialogu w stylu folderu.
wodny
27

Lepiej do tego użyć FolderBrowserDialog.

using (FolderBrowserDialog dlg = new FolderBrowserDialog())
{
    dlg.Description = "Select a folder";
    if (dlg.ShowDialog() == DialogResult.OK)
    {
        MessageBox.Show("You selected: " + dlg.SelectedPath);
    }
}
Ryan Farley
źródło
9
Wiem, że lepiej jest użyć FolderBrowserDialog. Jestem ciekawy, jak to zrobiono, niezależnie od tego. FolderBrowserDialog i tak śmierdzi na wiele sposobów; nawet w Vista nie ma paska miejsc. Zabawne, jak to jest lepsze, że MS jak dotąd unikało tego w 3 wersjach VS.
OwenP,
24
FolderBrowserDialog ma wiele problemów z użytecznością. Nie zastanawiałbym się nad umieszczeniem go w aplikacji. Zobacz mój post dla dialogu, który ma znacznie lepszą użyteczność
Scott Wiśniewski
6
FolderBrowserDialog nie pozwala na: - wpisywanie / wklejanie pełnych ścieżek w polu tekstowym u dołu - używanie paska „Ulubione łącza” w systemie Vista - korzystanie z wyszukiwania w
systemie
89
FolderBrowserDialog to naprawdę okropny interfejs użytkownika.
mackenir
32
Poważnie, ludzie, PROSZĘ przestańcie wprowadzać to irytujące okno dialogowe do swoich aplikacji. Ma BARDZO ZŁY UI, jak podkreślono we wcześniejszych komentarzach.
Roman Starkov
23

Po godzinach poszukiwań znalazłem tę odpowiedź przez leetNightShade do działającego rozwiązania .

Są trzy rzeczy, które moim zdaniem sprawiają, że to rozwiązanie jest znacznie lepsze niż wszystkie inne.

  1. Jest prosty w użyciu. Wymaga tylko dołączenia dwóch plików (które i tak można połączyć z jednym) w projekcie.
  2. Powraca do standardowego folderu FolderBrowserDialog, gdy jest używany w systemach XP lub starszych.
  3. Autor udziela zgody na użycie kodu w dowolnym celu, który uzna za odpowiedni.

    Nie ma licencji jako takiej, którą możesz wziąć i zrobić z kodem, co chcesz.

Pobierz kod tutaj .

Alex Essilfie
źródło
@MattDavis: Potwierdziłem, że działa na .NET Framework 4.0 (zarówno profil standardowy, jak i klient). Upewnij się tylko, że do projektu dodano zarówno FolderSelectDialog.cs, jak i Reflector.cs. Jedna rzecz ... czy działasz na systemie Windows 8? Testowałem na komputerze z Win7.
Alex Essilfie
@Alex Essilfie, masz rację. Musiałem zrobić coś złego, wciągając to do mojego projektu. Dla jasności usunę mój wcześniejszy komentarz.
Matt Davis
Przejrzałem wiele opcji i uważam, że ta jest najlepsza. Polecam
Jaded
Dla mnie pracował w systemie Windows 10. Dobre proste rozwiązanie
David Wilton,
muszą szanować przełączanie awaryjne w starszych systemach
Mike M,
17

Dokładna kopia audio działa w ten sposób w systemie Windows XP. Wyświetla się standardowe okno dialogowe otwierania pliku, ale pole nazwy pliku zawiera tekst „Nazwa pliku zostanie zignorowana”.

Zgaduję tutaj, ale podejrzewam, że ciąg jest wstrzykiwany do kontrolki edycji pola kombi za każdym razem, gdy wprowadzana jest znacząca zmiana w oknie dialogowym. Dopóki pole nie jest puste, a flagi okien dialogowych są ustawione tak, aby nie sprawdzały istnienia pliku, okno dialogowe można normalnie zamknąć.

Edycja: jest to o wiele łatwiejsze niż myślałem. Oto kod w C ++ / MFC, możesz przetłumaczyć go na wybrane środowisko.

CFileDialog dlg(true, NULL, "Filename will be ignored", OFN_HIDEREADONLY | OFN_NOVALIDATE | OFN_PATHMUSTEXIST | OFN_READONLY, NULL, this);
dlg.DoModal();

Edycja 2: To powinno być tłumaczenie na C #, ale nie mówię biegle w C #, więc nie strzelaj do mnie, jeśli to nie działa.

OpenFileDialog openFileDialog1 = new OpenFileDialog();

openFileDialog1.FileName = "Filename will be ignored";
openFileDialog1.CheckPathExists = true;
openFileDialog1.ShowReadOnly = false;
openFileDialog1.ReadOnlyChecked = true;
openFileDialog1.CheckFileExists = false;
openFileDialog1.ValidateNames = false;

if(openFileDialog1.ShowDialog() == DialogResult.OK)
{
    // openFileDialog1.FileName should contain the folder and a dummy filename
}

Edycja 3: W końcu spojrzał na właściwe okno dialogowe w Visual Studio 2005 (wcześniej nie miałem do niego dostępu). To nie jest standardowe okno dialogowe otwierania pliku! Jeśli sprawdzisz okna w Spy ++ i porównasz je ze standardowym otwartym plikiem, zobaczysz, że struktura i nazwy klas nie pasują. Gdy przyjrzysz się uważnie, możesz również zauważyć pewne różnice między zawartością okien dialogowych. Doszedłem do wniosku, że Microsoft całkowicie zastąpił standardowe okno dialogowe w Visual Studio, aby nadać mu tę funkcję. Moje rozwiązanie lub coś podobnego będzie tak blisko, jak to tylko możliwe, chyba że zechcesz napisać kod od zera.

Mark Ransom
źródło
17

OK, pozwól mi spróbować połączyć pierwszą kropkę ;-) Trochę gry ze Spy ++ lub Winspector pokazuje, że pole tekstowe Folder w Lokalizacji projektu VS jest dostosowaniem standardowego okna dialogowego. To nie jest to samo pole, co pole tekstowe z nazwą pliku w standardowym oknie dialogowym pliku, takim jak to w Notatniku.

Odtąd, jak sądzę, VS ukrywa nazwę pliku i pola tekstowe / kombinacje pól tekstowych i używa niestandardowego szablonu okna dialogowego, aby dodać własną część na dole okna dialogowego.

EDYCJA: Oto przykład takiej modyfikacji i jak to zrobić (w Win32. Nie .NET):

m_ofn jest strukturą OPENFILENAME, która stanowi podstawę okna dialogowego pliku. Dodaj te 2 linie:

  m_ofn.lpTemplateName = MAKEINTRESOURCE(IDD_FILEDIALOG_IMPORTXLIFF);
  m_ofn.Flags |= OFN_ENABLETEMPLATE;

gdzie IDD_FILEDIALOG_IMPORTXLIFF to niestandardowy szablon okna dialogowego, który zostanie dodany w dolnej części okna dialogowego. Zobacz część w kolorze czerwonym poniżej. (źródło: apptranslator.com )alternatywny tekst

W takim przypadku dostosowana część jest tylko etykietą + hiperłączem, ale może to być dowolne okno dialogowe. Może zawierać przycisk OK, który pozwoliłby nam zweryfikować wybór tylko folderu.

Ale jak pozbyliśmy się niektórych elementów sterujących w standardowej części okna dialogowego, nie wiem.

Więcej szczegółów w tym artykule MSDN .

Serge Wautier
źródło
1
To brzmi jak niektóre wyjaśnienia, które słyszałem w przeszłości, ale nigdy nie widziałem demonstracji tej koncepcji. Czy istnieją instrukcje w dokumentacji MSDN na ten temat?
OwenP,
10

Możesz podklasować okno dialogowe pliku i uzyskać dostęp do wszystkich jego elementów sterujących. Każdy ma identyfikator, którego można użyć do uzyskania uchwytu okna. Następnie możesz je wyświetlać i ukrywać, otrzymywać od nich wiadomości o zmianach wyboru itp. Wszystko zależy od tego, ile wysiłku chcesz podjąć.

Skorzystaliśmy z obsługi klasy WTL i dostosowaliśmy okno dialogowe pliku, aby zawierało niestandardowy pasek miejsc i widoki COM wtyczki.

MSDN zawiera informacje o tym, jak to zrobić za pomocą Win32, ten artykuł CodeProject zawiera przykład , a ten artykuł CodeProject zawiera przykład .NET .

Jeff Yates
źródło
10

Możesz użyć takiego kodu

  • Filtr to ukryj pliki
  • Nazwa pliku to ukryj pierwszy tekst

Aby zaawansować ukrywanie pola tekstowego dla nazwy pliku, musisz spojrzeć na OpenFileDialogEx

Kod:

{
    openFileDialog2.FileName = "\r";
    openFileDialog1.Filter = "folders|*.neverseenthisfile";
    openFileDialog1.CheckFileExists = false;
    openFileDialog1.CheckPathExists = false;
}
Avram
źródło
Proste i jest to, czego potrzebuję dla systemu Windows 7+
Hao Nguyen
Również flagi OFN_NOVALIDATE są wymagane
Goblin Alchemist
5

Zakładam, że korzystasz z systemu Vista przy użyciu VS2008? W takim przypadku myślę, że przy wywołaniu okna dialogowego pliku Vista IFileDialog używana jest opcja FOS_PICKFOLDERS . Obawiam się, że w kodzie .NET wymagałoby to dużo niepoprawnego kodu interoperacji P / Invoke, aby mógł działać.

Duncan Smart
źródło
1
Specyficzne dla systemu Vista; Po raz pierwszy zobaczyłem to w VS 2003 na Windows XP.
OwenP,
2

Pierwsze rozwiązanie

Opracowałem to jako oczyszczoną wersję okna wyboru folderów w stylu .NET Win 7 w stylu Billa Seddona z lyquidity.com (nie mam powiązania). (Dowiedziałem się o jego kodzie z innej odpowiedzi na tej stronie ). Napisałem własny, ponieważ jego rozwiązanie wymaga dodatkowej klasy Reflection, która nie jest potrzebna do tego ukierunkowanego celu, wykorzystuje kontrolę przepływu opartą na wyjątkach, nie buforuje wyników swoich wywołań refleksji. Zauważ, że zagnieżdżona VistaDialogklasa statyczna jest taka, że ​​jej statyczne zmienne odbicia nie próbują zapełnić się, jeśli Showmetoda nigdy nie zostanie wywołana. Powraca do okna dialogowego sprzed Visty, jeśli nie jest w wystarczająco wysokiej wersji Windows. Powinien działać w Windows 7, 8, 9, 10 i wyższych (teoretycznie).

using System;
using System.Reflection;
using System.Windows.Forms;

namespace ErikE.Shuriken {
    /// <summary>
    /// Present the Windows Vista-style open file dialog to select a folder. Fall back for older Windows Versions
    /// </summary>
    public class FolderSelectDialog {
        private string _initialDirectory;
        private string _title;
        private string _fileName = "";

        public string InitialDirectory {
            get { return string.IsNullOrEmpty(_initialDirectory) ? Environment.CurrentDirectory : _initialDirectory; }
            set { _initialDirectory = value; }
        }
        public string Title {
            get { return _title ?? "Select a folder"; }
            set { _title = value; }
        }
        public string FileName { get { return _fileName; } }

        public bool Show() { return Show(IntPtr.Zero); }

        /// <param name="hWndOwner">Handle of the control or window to be the parent of the file dialog</param>
        /// <returns>true if the user clicks OK</returns>
        public bool Show(IntPtr hWndOwner) {
            var result = Environment.OSVersion.Version.Major >= 6
                ? VistaDialog.Show(hWndOwner, InitialDirectory, Title)
                : ShowXpDialog(hWndOwner, InitialDirectory, Title);
            _fileName = result.FileName;
            return result.Result;
        }

        private struct ShowDialogResult {
            public bool Result { get; set; }
            public string FileName { get; set; }
        }

        private static ShowDialogResult ShowXpDialog(IntPtr ownerHandle, string initialDirectory, string title) {
            var folderBrowserDialog = new FolderBrowserDialog {
                Description = title,
                SelectedPath = initialDirectory,
                ShowNewFolderButton = false
            };
            var dialogResult = new ShowDialogResult();
            if (folderBrowserDialog.ShowDialog(new WindowWrapper(ownerHandle)) == DialogResult.OK) {
                dialogResult.Result = true;
                dialogResult.FileName = folderBrowserDialog.SelectedPath;
            }
            return dialogResult;
        }

        private static class VistaDialog {
            private const string c_foldersFilter = "Folders|\n";

            private const BindingFlags c_flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
            private readonly static Assembly s_windowsFormsAssembly = typeof(FileDialog).Assembly;
            private readonly static Type s_iFileDialogType = s_windowsFormsAssembly.GetType("System.Windows.Forms.FileDialogNative+IFileDialog");
            private readonly static MethodInfo s_createVistaDialogMethodInfo = typeof(OpenFileDialog).GetMethod("CreateVistaDialog", c_flags);
            private readonly static MethodInfo s_onBeforeVistaDialogMethodInfo = typeof(OpenFileDialog).GetMethod("OnBeforeVistaDialog", c_flags);
            private readonly static MethodInfo s_getOptionsMethodInfo = typeof(FileDialog).GetMethod("GetOptions", c_flags);
            private readonly static MethodInfo s_setOptionsMethodInfo = s_iFileDialogType.GetMethod("SetOptions", c_flags);
            private readonly static uint s_fosPickFoldersBitFlag = (uint) s_windowsFormsAssembly
                .GetType("System.Windows.Forms.FileDialogNative+FOS")
                .GetField("FOS_PICKFOLDERS")
                .GetValue(null);
            private readonly static ConstructorInfo s_vistaDialogEventsConstructorInfo = s_windowsFormsAssembly
                .GetType("System.Windows.Forms.FileDialog+VistaDialogEvents")
                .GetConstructor(c_flags, null, new[] { typeof(FileDialog) }, null);
            private readonly static MethodInfo s_adviseMethodInfo = s_iFileDialogType.GetMethod("Advise");
            private readonly static MethodInfo s_unAdviseMethodInfo = s_iFileDialogType.GetMethod("Unadvise");
            private readonly static MethodInfo s_showMethodInfo = s_iFileDialogType.GetMethod("Show");

            public static ShowDialogResult Show(IntPtr ownerHandle, string initialDirectory, string title) {
                var openFileDialog = new OpenFileDialog {
                    AddExtension = false,
                    CheckFileExists = false,
                    DereferenceLinks = true,
                    Filter = c_foldersFilter,
                    InitialDirectory = initialDirectory,
                    Multiselect = false,
                    Title = title
                };

                var iFileDialog = s_createVistaDialogMethodInfo.Invoke(openFileDialog, new object[] { });
                s_onBeforeVistaDialogMethodInfo.Invoke(openFileDialog, new[] { iFileDialog });
                s_setOptionsMethodInfo.Invoke(iFileDialog, new object[] { (uint) s_getOptionsMethodInfo.Invoke(openFileDialog, new object[] { }) | s_fosPickFoldersBitFlag });
                var adviseParametersWithOutputConnectionToken = new[] { s_vistaDialogEventsConstructorInfo.Invoke(new object[] { openFileDialog }), 0U };
                s_adviseMethodInfo.Invoke(iFileDialog, adviseParametersWithOutputConnectionToken);

                try {
                    int retVal = (int) s_showMethodInfo.Invoke(iFileDialog, new object[] { ownerHandle });
                    return new ShowDialogResult {
                        Result = retVal == 0,
                        FileName = openFileDialog.FileName
                    };
                }
                finally {
                    s_unAdviseMethodInfo.Invoke(iFileDialog, new[] { adviseParametersWithOutputConnectionToken[1] });
                }
            }
        }

        // Wrap an IWin32Window around an IntPtr
        private class WindowWrapper : IWin32Window {
            private readonly IntPtr _handle;
            public WindowWrapper(IntPtr handle) { _handle = handle; }
            public IntPtr Handle { get { return _handle; } }
        }
    }
}

Używa się go tak jak w formularzu Windows:

var dialog = new FolderSelectDialog {
    InitialDirectory = musicFolderTextBox.Text,
    Title = "Select a folder to import music from"
};
if (dialog.Show(Handle)) {
    musicFolderTextBox.Text = dialog.FileName;
}

Możesz oczywiście bawić się z jego opcjami i właściwościami, które ujawnia. Na przykład umożliwia wielokrotne wybieranie w oknie dialogowym w stylu Vista.

Drugie rozwiązanie

Simon Mourier udzielił odpowiedzi, która pokazuje, jak wykonać dokładnie to samo zadanie, używając bezpośrednio interfejsu API systemu Windows, chociaż jego wersja musiałaby zostać uzupełniona, aby używać starszego stylu okna dialogowego, jeśli jest w starszej wersji systemu Windows. Niestety nie znalazłem jeszcze jego posta, gdy opracowałem swoje rozwiązanie. Nazwij swoją truciznę!

ErikE
źródło
Podobny przykład użycia do wywołania tego dokładnego okna dialogowego jako okna dialogowego (np. Z aplikacji konsolowych) z pustym uchwytem: kompiluje od razu: var dialog = new FolderSelectDialog {InitialDirectory = "C: \\", Title = "Wybierz folder do importowania muzyki z "}; if (dialog.Show ()) {string myFolder = dialog.FileName; }
Philm
Uwaga: Mój przykład użycia jako komentarz jest trudny do odczytania, dlatego: Najważniejsza zmiana na „przykład” pierwotnego użycia: Użyj przecinka między katalogiem początkowym a tytułem ..
Philm
1

Wypróbuj ten z Codeproject (kredyt dla Nitron):

Myślę, że mówisz o tym samym oknie dialogowym - może pomogłoby Ci to, jeśli dodasz zrzut ekranu?

bool GetFolder(std::string& folderpath, const char* szCaption=NULL, HWND hOwner=NULL)
{
    bool retVal = false;

    // The BROWSEINFO struct tells the shell how it should display the dialog.
    BROWSEINFO bi;
    memset(&bi, 0, sizeof(bi));

    bi.ulFlags   = BIF_USENEWUI;
    bi.hwndOwner = hOwner;
    bi.lpszTitle = szCaption;

    // must call this if using BIF_USENEWUI
    ::OleInitialize(NULL);

    // Show the dialog and get the itemIDList for the selected folder.
    LPITEMIDLIST pIDL = ::SHBrowseForFolder(&bi);

    if(pIDL != NULL)
    {
        // Create a buffer to store the path, then get the path.
        char buffer[_MAX_PATH] = {'\0'};
        if(::SHGetPathFromIDList(pIDL, buffer) != 0)
        {
            // Set the string value.
            folderpath = buffer;
            retVal = true;
        }       

        // free the item id list
        CoTaskMemFree(pIDL);
    }

    ::OleUninitialize();

    return retVal;
}
demoncodemonkey
źródło
images.google.com/… Przeszukuj, gdy masz wątpliwości. Opisałem, co chciałem, a FolderBrowserDialog został już zdyskwalifikowany jako odpowiedź.
OwenP,
„Wiem o folderze FolderBrowserDialog, ale tak naprawdę nigdy nie podobało mi się to okno dialogowe. Zaczyna się zbyt małe i nie pozwala mi skorzystać z możliwości wpisania ścieżki”. Zrób trochę badań sam - możesz tam wpisać ścieżkę. W każdym razie myślę, że to trochę dwuznaczne pytanie, więc powodzenia.
demoncodemonkey
@demoncodemonkey: Nie możesz wpisać części ścieżki, a następnie przejść do żądanego celu. Zdecydowanie nie tak wygodne, jak opcje oferowane przez FileOpenDialog.
Treb
1

W systemie Vista można używać IFileDialog z zestawem opcji FOS_PICKFOLDERS. Spowoduje to wyświetlenie okna podobnego do OpenFileDialog, w którym możesz wybrać foldery:

var frm = (IFileDialog)(new FileOpenDialogRCW());
uint options;
frm.GetOptions(out options);
options |= FOS_PICKFOLDERS;
frm.SetOptions(options);

if (frm.Show(owner.Handle) == S_OK) {
    IShellItem shellItem;
    frm.GetResult(out shellItem);
    IntPtr pszString;
    shellItem.GetDisplayName(SIGDN_FILESYSPATH, out pszString);
    this.Folder = Marshal.PtrToStringAuto(pszString);
}

W starszych wersjach systemu Windows zawsze możesz zastosować trick, wybierając dowolny plik w folderze.

Przykład działania, który działa na .NET Framework 2.0 i nowszych, można znaleźć tutaj .

Josip Medved
źródło
1

Możesz użyć takiego kodu

Filtr jest pustym ciągiem. Nazwa pliku to AnyName, ale nie jest pusta

        openFileDialog.FileName = "AnyFile";
        openFileDialog.Filter = string.Empty;
        openFileDialog.CheckFileExists = false;
        openFileDialog.CheckPathExists = false;
lantran
źródło
6
Wiem, że jest to stary post, ale ze względu na każdego, kto chce to wypróbować, tak naprawdę nie działa, chyba że katalog, który chcesz otworzyć, absolutnie nie ma katalogów potomnych. Więc jeśli chcę pozwolić mojemu użytkownikowi na przeglądanie folderu i wybranie go oraz wypełnienie ścieżki folderu w polu tekstowym, użytkownik nigdy nie może wybrać C: \ SomeParentDir, jeśli istnieje katalog C: \ SomeParentDir \ SomeChildDir, ponieważ wybranie „Otwórz „po prostu przeniesie Cię do katalogu potomnego.
Jim
Dobra próba ... ale skutkuje to strasznym interfejsem użytkownika, ponieważ „AnyFile” w polu tekstowym czeka tylko na zastąpienie tekstu przez użytkownika. Poza tym użytkownik może również wybierać pliki - to nie wystarczy. ale niezła próba ..
GY
-1

Wiem, że pytanie dotyczyło konfiguracji, OpenFileDialogale widząc, że Google mnie tu przywiodło, mogę również zauważyć, że jeśli TYLKO szukasz folderów, powinieneś użyć FolderBrowserDialogZamiast tego, jak odpowiedziałem inne SO pytanie poniżej

Jak określić ścieżkę za pomocą okna dialogowego Otwórz plik w vb.net?

AltF4_
źródło
Zwodniczy. 1) To nie jedyny wybór; 2) W większości przypadków nie jest to dobry wybór; Mimo to wymaga najmniejszego kodu, który jest wymieniany przez więcej czasu spędzonego przez użytkownika końcowego.
Meow Cat 2012