В VS .NET, когда вы выбираете папку для проекта, отображается диалоговое окно, которое выглядит как OpenFileDialog или SaveFileDialog, но настроено для приема только папок. С тех пор, как я это увидел, я хотел знать, как это делается. Я знаю о FolderBrowserDialog, но мне никогда не нравился этот диалог. Он начинается слишком маленьким и не позволяет мне вводить путь.
Я почти уверен, что на данный момент нет способа сделать это из .NET, но мне так же любопытно, как вы это делаете и из неуправляемого кода. Если не считать полного переопределения диалогового окна с нуля, как вы измените диалоговое окно, чтобы оно имело такое поведение?
Я также хотел бы повторить, что я знаю о FolderBrowserDialog, но иногда мне не нравится его использовать, помимо искреннего любопытства, как настроить диалог таким образом. Совет мне просто использовать FolderBrowserDialog помогает мне поддерживать единообразие интерфейса пользователя, но не удовлетворяет мое любопытство, поэтому это не будет считаться ответом.
Это тоже не особенность Vista; Я видел этот диалог с VS .NET 2003, так что он возможен в Win2k и WinXP. Это не столько вопрос «Я хочу знать, как это сделать», сколько вопрос «Мне было любопытно по этому поводу с тех пор, как я впервые захотел сделать это в VS 2003». Я понимаю, что в файловом диалоге Vista есть возможность сделать это, но он работает в XP, поэтому я знаю, что они сделали что нибудь, чтобы заставить его работать. Ответы, относящиеся к Vista, не являются ответами, потому что Vista не существует в контексте вопроса.
Обновление: я принимаю ответ Скотта Вишневски, потому что он поставляется с рабочим образцом, но я думаю, что Серж заслуживает похвалы за то, что указал на настройку диалога (который, по общему признанию, неприятен для .NET, но работает делает), и Марк Рэнсом за выяснение этого MS наверное накатил кастомный диалог для этой задачи.
Отправьте это как ответ, он выполнил свою работу для моего проекта.
@Riju - dialog.FileName = "Folder Selection" должен быть dialog.FileName = "Folder Selection." с конечным периодом? в любом случае я не могу заставить его работать в PowerShell при втором щелчке «Открыть» в любом случае. Он продолжает говорить, что файл не найден, хотя CheckFileExists предположительно ложен
nvm, в настройке PowerShell dialog.CheckFileExists = 0 вместо false решил мою проблему
Вы пробовали Диалоги Ookii для WPF?





Лучше использовать для этого FolderBrowserDialog.
using (FolderBrowserDialog dlg = new FolderBrowserDialog())
{
dlg.Description = "Select a folder";
if (dlg.ShowDialog() == DialogResult.OK)
{
MessageBox.Show("You selected: " + dlg.SelectedPath);
}
}
+1, браузер папок Visual Studio, похожий на файловый браузер, - плохая идея
Я знаю, что использование FolderBrowserDialog - это лучше. Мне любопытно, как это было сделано, несмотря ни на что. В любом случае, FolderBrowserDialog во многих отношениях имеет неприятный запах; даже в Vista нет панели мест. Забавно, если это лучше, MS до сих пор избегала этого в версиях 3 VS.
FolderBrowserDialog имеет много проблем с удобством использования. Я бы не стал рассматривать его в приложении. Смотрите в моем сообщении диалог, который намного удобнее
FolderBrowserDialog не позволяет: - вводить / вставлять полные пути в текстовое поле внизу - использовать панель «Избранные ссылки» в Vista - использовать поиск в Vista
FolderBrowserDialog - действительно ужасный элемент пользовательского интерфейса.
Серьезно, люди, ПОЖАЛУЙСТА, перестаньте вставлять этот надоедливый диалог в свои приложения. У него ОЧЕНЬ ПЛОХОЙ пользовательский интерфейс, как отмечалось в предыдущих комментариях.
Конечно, FolderBrowserDialog - это отстойный диалог. Мне это тоже не нравится. Но мой ответ для OP заключался в том, что диалог, предназначенный для выбора папки, даже плохо спроектированной, был лучшим путем, чем обман OpenFileDialog, позволяющий выбирать только папки. Это только сбивает с толку типичного пользователя IMO (признайтесь, пользователи глупы).
@Ryan Я согласен, что просто заменять его другим дерьмовым диалогом - это плохо, но Open Folder кажется официальным в Vista. Также stackoverflow.com/questions/238177/worst-ui-youve-ever-used/… :)
@romkyns источник FolderBrowserDialog ХУЖЕ.
Хуже, чем диалог, то, что для большинства приложений это всего лишь один флаг (BIF_USENEWUI), чтобы сделать эту мерзость терпимой, и довольно тривиальный обратный вызов, чтобы дать ему первоначальный выбор.
Именно то, что мне нужно.
Я должен согласиться, что это не по существу вопроса. Я также согласен, что ненавижу поле FolderBrowser, но это не имеет значения ... OP не просил сравнения.
Я полагаю, вы в Vista используете VS2008? В этом случае я думаю, что Опция FOS_PICKFOLDERS используется при вызове файлового диалогового окна Vista IFileDialog. Боюсь, что в .NET-коде это потребовало бы большого количества корявого кода взаимодействия P / Invoke для начала работы.
Специально для Vista; Впервые я увидел это на VS 2003 в Windows XP.
Хорошо, позвольте мне попробовать соединить первую точку ;-) Немного поиграв со Spy ++ или Winspector, можно увидеть, что текстовое поле «Папка» в расположении проекта VS является настройкой стандартного диалогового окна. Это не то же самое поле, что и текстовое поле имени файла в стандартном диалоговом окне файла, например, в Блокноте.
С этого момента, как я понимаю, VS скрывает текстовые поля / поля со списком имени файла и типа файла и использует настраиваемый шаблон диалогового окна для добавления своей собственной части в нижнюю часть диалогового окна.
Обновлено: Вот пример такой настройки и как это сделать (в Win32. Не .NET):
m_ofn - это структура OPENFILENAME, которая лежит в основе диалогового окна файла. Добавьте эти 2 строки:
m_ofn.lpTemplateName = MAKEINTRESOURCE(IDD_FILEDIALOG_IMPORTXLIFF);
m_ofn.Flags |= OFN_ENABLETEMPLATE;
где IDD_FILEDIALOG_IMPORTXLIFF - это настраиваемый шаблон диалогового окна, который будет добавлен в нижней части диалогового окна. См. Часть, выделенную красным ниже.

(source: apptranslator.com)
В этом случае настраиваемая часть представляет собой только метку + гиперссылку, но это может быть любой диалог. Он может содержать кнопку ОК, которая позволит нам подтверждать выбор только папки.
Но как бы мы избавились от некоторых элементов управления в стандартной части диалога, я не знаю.
Подробнее в эта статья MSDN.
Это похоже на некоторые объяснения, которые я слышал в прошлом, но я никогда не видел демонстрации концепции. Есть ли в документации MSDN пошаговые инструкции по этому поводу?
Попробуйте это от Кодпроект (кредит Nitron):
Я думаю, это тот же диалог, о котором вы говорите - может, поможет, если вы добавите скриншот?
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;
}
«Я знаю о FolderBrowserDialog, но мне никогда не нравился этот диалог. Он начинается слишком маленьким и не позволяет мне воспользоваться возможностью ввести путь». Проведите небольшое исследование самостоятельно - вы можете ввести туда путь. В любом случае, я думаю, что это немного неоднозначный вопрос, так что удачи с ним.
@demoncodemonkey: вы не можете ввести часть пути, а затем перейти к желаемой цели. Далеко не так удобны, как варианты, предлагаемые FileOpenDialog.
Вы можете создать подкласс файлового диалога и получить доступ ко всем его элементам управления. У каждого есть идентификатор, который можно использовать для получения дескриптора окна. Затем вы можете отображать и скрывать их, получать от них сообщения об изменениях выбора и т. д. И т. Д. Все зависит от того, сколько усилий вы хотите приложить.
Мы сделали это, используя поддержку классов WTL, и настроили диалоговое окно файла, включив в него настраиваемую панель мест и представления COM плагина.
MSDN предоставляет информацию о том, как это сделать с помощью Win32, эта статья CodeProject включает пример и в этой статье CodeProject приводится пример .NET..
Точная аудиокопия работает таким образом в Windows XP. Отображается стандартный диалог открытия файла, но поле имени файла содержит текст «Имя файла будет проигнорировано».
Просто догадываюсь, но я подозреваю, что строка вводится в элемент управления редактирования поля со списком каждый раз, когда в диалоговом окне вносятся значительные изменения. Пока поле не пустое, а флажки диалогового окна не проверяют наличие файла, диалоговое окно можно закрыть обычным образом.
Редактировать: это намного проще, чем я думал. Вот код на C++ / MFC, вы можете перевести его в среду по вашему выбору.
CFileDialog dlg(true, NULL, "Filename will be ignored", OFN_HIDEREADONLY | OFN_NOVALIDATE | OFN_PATHMUSTEXIST | OFN_READONLY, NULL, this);
dlg.DoModal();
Изменить 2: Это должен быть перевод на C#, но я плохо говорю на C#, поэтому не стреляйте в меня, если это не сработает.
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
}
Изменить 3: Наконец, взглянул на рассматриваемый диалог в Visual Studio 2005 (раньше у меня не было доступа к нему). Это не стандартный диалог открытия файла! Если вы проверите окна в Spy ++ и сравните их со стандартным открытым файлом, вы увидите, что имена структур и классов не совпадают. Если вы присмотритесь, вы также можете заметить некоторые различия между содержимым диалоговых окон. Я пришел к выводу, что Microsoft полностью заменила стандартный диалог в Visual Studio, чтобы дать ему такую возможность. Мое решение или что-то подобное будет максимально приближенным к вам, если только вы не захотите написать собственное кодирование с нуля.
Пакет Ookii.Dialogs содержит управляемую оболочку вокруг нового диалогового окна браузера папок (в стиле Vista). Он также постепенно ухудшается в старых операционных системах.
Круто, это открытый исходный код под лицензией BSD!
единственная проблема в том, что я не позволю использовать профиль клиента .NET Framework в качестве цели.
Очень красивое решение. На мой взгляд, это лучший ответ. Именно то, что искал 3 года.
К сожалению, у него есть некрасивая ошибка в XP, и он не обновляется с 2009 года. Ошибка: тарабарщина в верхнем ряду при использовании "description": vidcoder.codeplex.com/workitem/32
Еще одна проблема с этим решением: оно не позволяет пользователю вставить несуществующий путь. Сравнительно мелкий, но все же жаль.
Лучший ответ практичный для тех, кому нужен диалог папки в стиле OpenFileDialog.
Исходный код компилируется и запускается без ошибок, но может работать только в ОС более поздних версий, чем Vista.
Отлично работает даже в VS2017 с консольным приложением F#. Просто добавьте ссылку на PresentationFramework и Ookii.Dialogs.Wpf.dll (где бы он ни находился; я помещаю копию в папку своего проекта), а затем вызовите его с помощью кода F# следующим образом: откройте Ookii.Dialogs.Wpf [
Вы можете использовать такой код:
Для расширенного скрытия текстового поля для имени файла вам нужно посмотреть
OpenFileDialogEx
Код:
.
{
openFileDialog2.FileName = "\r";
openFileDialog1.Filter = "folders|*.neverseenthisfile";
openFileDialog1.CheckFileExists = false;
openFileDialog1.CheckPathExists = false;
}
Просто и это то, что мне нужно для Windows 7+
Также OFN_NOVALIDATE требуется во флагах
У меня есть написанное мною диалоговое окно OpenFileOrFolder, которое позволяет открывать папку или файл.
Если вы установите для его значения AcceptFiles значение false, он будет работать только в режиме принятия папки.
Вы можете скачать исходный код с GitHub здесь
Очень интересно и определенно так сложно, как я предполагал. Есть ли шанс аннотировать его и указать, что он делает? Это вместе с другими комментариями заставляет меня поверить, что MS, вероятно, просто свернула свой собственный диалог.
Я получаю следующую ошибку при попытке создать ваше решение ... к сожалению, C++ не является одной из моих сильных сторон ... Ошибка 1 не может открыть включаемый файл 'afxres.h'.
@SoMoS и другие с той же проблемой: в файле WindowsFormsApplication1.csproj отредактируйте строку 100, чтобы она соответствовала вашей настройке. В моем случае мне пришлось изменить «9.0» на «10.0» (дважды) и удалить «(x86)» (дважды).
Я думаю, что просто использовать Microsoft Windows API Pack - лучшее решение: stackoverflow.com/questions/31059/…
@PatrickKlug Мой диалог фактически позволяет вам открывать и файлы, и папки одновременно (т.е. он имеет режим, в котором «Выбрать файлы» и «Выбрать папки» одновременно верны). Но если вам это не нужно или вы предпочитаете тот, который от Microsoft, то во что бы то ни стало, пожалуйста, используйте его.
Это не совсем решение с перетаскиванием, в отличие от фреймворка Ookii. Я просто хочу, чтобы это работало, я не хочу возиться с исходниками.
+1 за очень хорошо (несмотря на глючную навигацию по библиотеке). Я бы рекомендовал вам поместить весь код в один файл или предоставить готовое решение для упрощения использования.
Я загрузил код (zip), нашел в нем файл .h (C) и скомпилировал его с ошибкой, например, не могу открыть включаемый файл «sal.h».
Я извлек его в какую-то папку, я открыл его в VS 2013, он сказал, что нужно внести некоторые изменения, чтобы открыть его в этом. Я сказал хорошо. Я нажал кнопку воспроизведения и получил эту ошибку. Он не выделяет какую-либо конкретную строку. i.imgur.com/wPa986V.png У меня Windows 7.
Это решение также не работает на VS2010 и VS2017!
Файл msbuild имеет настраиваемое действие, запускающее собственный компилятор ресурсов (rc.exe). Убедитесь, что у вас установлены инструменты C++. Возможно, вам также потребуется обновить пути в файле сборки. Вероятно, вы можете использовать переменные env. У меня больше нет компьютера с Windows, и его не было уже несколько лет, поэтому я не могу протестировать необходимые обновления сборки. Если вы хотите внести необходимые изменения в сборку, вы можете внести свой вклад в проект.
WindowsCodePack через встроенный NuGet настолько прост и, как кажется, хорошо используется, я думаю, что это лучший ответ.
Есть ошибка в системах с RAM> 8GB (uint maxVal). изменить hWnd.SendMessage (msg, InteropUtil.NumberOfFileChars, unchecked ((uint) buffer)); в hWnd.SendMessage (msg, InteropUtil.NumberOfFileChars, unchecked ((ulong) buffer)); Очевидно, измените сигнатуру функции. Решил мне окончательно проблемы
Вы можете использовать FolderBrowserDialogEx - многоразовая производная от встроенного FolderBrowserDialog. Это позволяет вам вводить путь, даже путь UNC. С его помощью вы также можете искать компьютеры или принтеры. Работает так же, как встроенный FBD, но ... лучше.
(Обновлено: я должен был указать, что в этом диалоговом окне можно настроить выбор файлов или папок.)
Полный исходный код (один короткий модуль C#). Свободный. MS-Public лицензия.
Код для его использования:
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;
}
Извините, если я обиделась, просто неприятно задавать вопрос и объяснять: «Я хочу именно эту вещь, а не эти другие вещи», и люди с радостью предлагают то, о чем не просили. Мне нужен диалог просмотра файлов, а не диалог браузера папок.
Формулировка вопроса для меня звучит так, как будто он запрашивает диалог выбора папки - разве это не так? Во всяком случае, это именно то, что я искал +1
Определенно лучший ответ на данный момент
Поддержка CodePlex прекращена. Ссылка больше не приведет вас туда, где вы хотели прыгнуть. Поскольку это, по сути, ответ только по ссылке, полезность ответа больше не дается.
Это не меняет того факта, что ответ по-прежнему является ответом только по ссылке. Отображение того, как использовать код, размещенный на стороннем ресурсе, перестает быть полезным, когда эта ссылка также становится временно или постоянно недоступной. Правила существуют по какой-то причине, и этот вклад противоречит этим правилам.
к сожалению, я не могу вставить в этот ответ весь интернет. OTOH, может быть, вы слишком остро реагируете? Посмотрите на любой другой ответ здесь; все они ссылаются на некоторую внешнюю библиотеку или среду выполнения, часто без ссылку! (Думаю, «погуглите сами») Итак ... мне кажется, что включить ссылку в ответ - не проблема. В любом случае, мне очень жаль, что вы не были в восторге от ответа.
Я посмотрел на ответ это, и он, по-видимому, не ссылается на сторонний ресурс. Итак, "каждый второй ответ" явно ошибочен. Если вы чувствуете, что я слишком остро реагирую, возможно, вам стоит поднять вопрос на мете, чтобы обсудить правила. Я не буду. Я просто применю их.
Есть пакет кода Windows API. У него много вещей, связанных с оболочкой, включая класс CommonOpenFileDialog (в пространстве имен Microsoft.WindowsAPICodePack.Dialogs). Это идеальное решение - обычный открытый диалог, в котором отображаются только папки.
Вот пример того, как его использовать:
CommonOpenFileDialog cofd = new CommonOpenFileDialog();
cofd.IsFolderPicker = true;
cofd.ShowDialog();
К сожалению, Microsoft больше не поставляет этот пакет, но несколько человек неофициально загрузили двоичные файлы в NuGet. Один пример можно найти здесь. Этот пакет предназначен только для оболочки. Если вам это нужно, у того же пользователя есть несколько других пакетов, которые предлагают больше функций, присутствующих в исходном пакете.
Я не знал, что это в Windows API Code Pack - спасибо, что указали на это.
Класс CommonOpenFileDialog существует только в Windows Vista или более поздних версиях, поэтому вызовет исключение в более старых операционных системах.
Не могли бы вы рассказать, как ссылаться на Windows API Code Pack?
Пакеты кода Windows API доступны через Nuget по адресу: - nuget.org/packages/Windows7APICodePack-Shell и nuget.org/packages/Windows7APICodePack-Core.
Блестяще! На самом деле было так просто, как рекламировалось. Я установил только упомянутый выше пакет Shell, и все заработало как шарм.
Кстати, класс CommonOpenFileDialog находится в пространстве имен Microsoft.WindowsAPICodePack.Dialogs (мне потребовалось время, чтобы найти его).
Действительно ли целесообразно использовать что-то, что больше не доступно из источника (Microsoft), что, если они удалят ссылки на это в более новых ОС? диалог больше не будет работать, и, как указано @Rahel, он также не имеет обратной совместимости. - Не лучшее окончательное решение, но +1 за интересное решение, и я уверен, что многие люди уже воспользовались им.
@morgb О, спасибо, что рассказал ... Я только что открыл "Обозреватель объектов" в моем VS, и вы знаете, насколько он медленный: P
идеально :) И легко доступен в VS ... просто поиск в диспетчере пакетов NuGet для "WindowsAPICodePack" дает много вариантов, таких как упомянутые примеры. Результат доступен после выбора (после закрытия диалога) в свойстве object.FileName.
В Vista вы можете использовать IFileDialog с установленной опцией FOS_PICKFOLDERS. Это приведет к отображению окна, подобного OpenFileDialog, в котором вы можете выбирать папки:
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);
}
Для более старых версий Windows вы всегда можете прибегнуть к уловке, выбрав любой файл в папке.
Рабочий пример, работающий на .NET Framework 2.0 и более поздних версиях, можно найти здесь.
Вы можете использовать такой код
Фильтр - пустая строка. Имя файла - AnyName, но не пустое.
openFileDialog.FileName = "AnyFile";
openFileDialog.Filter = string.Empty;
openFileDialog.CheckFileExists = false;
openFileDialog.CheckPathExists = false;
Я знаю, что это старый пост, но для всех, кто хочет попробовать, он на самом деле не работает, если в каталоге, который вы хотите открыть, нет абсолютно никаких дочерних каталогов. Поэтому, если я хочу позволить моему пользователю перейти к папке и выбрать ее, а также указать путь к папке в каком-либо текстовом поле, пользователь никогда не сможет выбрать C: \ SomeParentDir, если каталог C: \ SomeParentDir \ SomeChildDir существует, потому что выбрав «Открыть» "просто переносит вас в дочерний каталог.
Хорошая попытка ... но это приводит к ужасному пользовательскому интерфейсу, поскольку "AnyFile" в текстовом поле просто ждет, пока пользователь переопределит его текст ... кроме того, пользователь может также выбирать файлы - недостаточно хорошо. но хорошая попытка ..
После нескольких часов поиска я нашел этот ответ от leetNightShade до рабочее решение.
Я считаю, что есть три вещи, которые делают это решение намного лучше, чем все остальные.
There’s no license as such as you are free to take and do with the code what you will.
Загрузите код здесь.
@MattDavis: Я подтвердил, что он работает на .NET Framework 4.0 (как в стандартном, так и в клиентском профиле). Просто убедитесь, что в ваш проект добавлены и FolderSelectDialog.cs, и Reflector.cs. Одно но ... вы работаете на Windows 8? Тестировал на компьютере Win7.
@Alex Essilfie, вы правы. Я, должно быть, сделал что-то не так, включив это в свой проект. Я удалю свой предыдущий комментарий для ясности.
Пробежался по нескольким вариантам и подумал, что это лучший. Рекомендую.
У меня работал в windows 10. Хорошее простое решение
должны соблюдать отказоустойчивость в старых системах
Первое решение
Я разработал это как очищенную версию Диалог выбора папки в стиле .NET Win 7 Билла Седдона из lyquidity.com (я не принадлежу к группе). (Я узнал о его коде из другой ответ на этой странице). Я написал свой собственный, потому что его решение требует дополнительного класса Reflection, который не нужен для этой конкретной цели, использует управление потоком на основе исключений, не кэширует результаты своих вызовов отражения. Обратите внимание, что вложенный статический класс VistaDialog создан таким образом, что его статические переменные отражения не пытаются заполниться, если метод Show никогда не вызывается. Он возвращается к диалоговому окну до Vista, если не в достаточно высокой версии Windows. Должен работать в Windows 7, 8, 9, 10 и выше (теоретически).
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; } }
}
}
}
В Windows Form это используется так:
var dialog = new FolderSelectDialog {
InitialDirectory = musicFolderTextBox.Text,
Title = "Select a folder to import music from"
};
if (dialog.Show(Handle)) {
musicFolderTextBox.Text = dialog.FileName;
}
Вы, конечно, можете поэкспериментировать с его параметрами и тем, какие свойства он предоставляет. Например, он позволяет выполнять множественный выбор в диалоговом окне в стиле Vista.
Второе решение
Симон Мурье дал ответ, который показывает, как выполнить ту же самую работу, используя взаимодействие с Windows API напрямую, хотя его версия должна быть дополнена, чтобы использовать диалог старого стиля, если в более старой версии Windows. К сожалению, я еще не нашел его пост, когда работал над своим решением. Назови свой яд!
Аналогичный пример использования для вызова этого прекрасного диалога как диалогового окна (например, из приложений консольного типа) с пустым дескриптором: компилируется прямо из окна: var dialog = new FolderSelectDialog {InitialDirectory = "C: \\", Title = "Выберите папка для импорта музыки из "}; если (dialog.Show ()) {строка myFolder = dialog.FileName; }
Примечание. Мой пример использования в качестве комментария трудно читать, поэтому: Наиболее важное изменение в исходном использовании «пример»: используйте запятую между InitialDirectory и Title ..
Я знаю, что вопрос касался конфигурации OpenFileDialog, но, увидев, что Google привел меня сюда, я также могу указать, что если вы ТОЛЬКО ищете папки, вы должны использовать FolderBrowserDialog, вместо этого, как ответил другой вопрос SO ниже
Как указать путь с помощью диалога открытия файла в vb.net?
Вводящие в заблуждение. 1) Это нет единственный выбор; 2) В большинстве случаев это не лучший выбор; Тем не менее, для этого требуется минимум кода, за счет которого конечный пользователь тратит больше времени.
В библиотеке Диалоги Ookii для WPF есть класс, который обеспечивает реализацию диалогового окна браузера папок для WPF.
Также есть версия, которая работает с Windows Forms.
просто простое решение от codeproject codeproject.com/Articles/44914/… [Ключ к получению OpenFileDialog выбора файлов и папок - установить для свойств ValidateNames и CheckFileExists значение false (dialog.ValidateNames = false; dialog.CheckFileExists = false) и установить для FileName какое-то специальное ключевое слово, равное убедитесь, что папки выбраны (dialog.FileName = "Folder Selection";).]