Стилизация и многооконность

CommonOpenFileDialog в WPF: выбор файла и папки через WindowsAPICodePack-Shell

Открытие файлов и папок

С предыдущего полугодия мы уже с вами знаем, что с файлами мы работаем с помощью класса File, а с папками — с помощью Directory. Однако если в предыдущих практических мы делали выбор через Console.ReadLine(), вводя путь до нужного файла или папки, то в оконных приложениях у нас есть окно с выбором файла или папки — CommonOpenFileDialog. Его можно настроить как для файлов, так и для папок. Давайте научимся с ним работать.

Для начала, я создам какой-то базовый интерфейс с текстовым полем, где мы будем смотреть содержимое файла, и кнопку, нажимая на которую, мы будем выбирать файл. Кнопке я дам имя OpenBtn, тексту — FileTxt.

MainWindow с пустой областью для текста и кнопкой «Открыть файл» внизу

Обработаем нажатие на кнопку OpenBtn. Я хочу, чтобы при нажатии на эту кнопку появлялось диалоговое окно выбора файла. Раз мы уже знаем, что нам нужен класс CommonOpenFileDialog, давайте создадим переменную с типом данных этого класса. Этот тип данных заставляет нас думать дольше двух секунд, значит это у нас сложный тип данных.

private void OpenBtn_Click(object sender, RoutedEventArgs e)
{
CommonOpenFileDialog dialog = new CommonOpenFileDialog();
}

Однако создавая эту переменную, мы видим, что у нас появляется ошибка, и Alt+Enter не помогает.

Подсветка ошибки «не удалось найти тип CommonOpenFileDialog»

Почему так? Проблема в том, что нам нужно докачать пакет, чтобы работать с этим классом. Откроем управление пакетами NuGet через ПКМ по проекту → Управление пакетами NuGet.

Перейдем в обзор пакетов и в поиске напишем «WindowsAPICodePack-Shell». Нам нужен пакет, который был установлен более двух миллионов раз. Версия пакета не важна.

NuGet с найденным WindowsAPICodePack-Shell автора Aybe

После ее установки мы можем спокойно вернуться к нашему коду, и, нажав Alt+Enter или на лампочку, подключить нужную библиотеку — Microsoft.WindowsAPICodePack.Dialogs.

Подсказка IDE добавить using Microsoft.WindowsAPICodePack.Dialogs

После этого мы сможем работать с нашей переменной dialog, где у нас будет хранится вся информация об окошке выбора файла и о выбранном файле соответственно.

Мы хотим открыть это окно и знать, когда оно закроется. Значит, мы понимаем, что это окно диалоговое, и открыть мы его хотим с помощью ShowDialog().

private void OpenBtn_Click(object sender, RoutedEventArgs e)
{
CommonOpenFileDialog dialog = new CommonOpenFileDialog();
dialog.ShowDialog();
}

Теперь, при нажатии на кнопку, у нас откроется диалоговое окно с выбором файла. По умолчанию, мы можем выбрать любой файл любого формата.

Открыт диалог выбора файла с одним файлом «создатели программы.txt» на рабочем столе

После выбора файла и нажатия на кнопку «Открыть», мое диалоговое окно закрывается, а на интерфейсе ничего не появится. Логично, потому что код мы еще для этого не прописали. Однако, как его прописать, как мне получить выбранный файл?

Во-первых, давайте вспомним, что все подтверждающие кнопки в диалоговых окнах («да», «открыть», «установить» и прочее) имеют под собой DialogResult = true. Значит, мне нужно сделать условие, что если мы открываем выбранный нами файл, то нам нужно взять его имя, и уже тогда работать с ним через File.

Однако так как это немного не простое окно, а окно выбора файла, то и результат у него будет не типа данных bool?, а тип данных CommonFileDialogResult. Это у нас enum, так что удовлетворяющее нас условие будет выглядеть как CommonFileDialogResult.Ok.

private void OpenBtn_Click(object sender, RoutedEventArgs e)
{
CommonOpenFileDialog dialog = new CommonOpenFileDialog();
CommonFileDialogResult result = dialog.ShowDialog();
if (result == CommonFileDialogResult.Ok)
{
// выбрать файл
}
}

А чтобы взять файл, который я выбрала, мне необходимо взять FileName из моей переменной с окошком, т.е. из dialog. Внутри него будет хранится полный путь до файла. С помощью него я могу прочитать весь текст из файла — File.ReadAllText(dialog.FileName).

private void OpenBtn_Click(object sender, RoutedEventArgs e)
{
CommonOpenFileDialog dialog = new CommonOpenFileDialog();
CommonFileDialogResult result = dialog.ShowDialog();
if (result == CommonFileDialogResult.Ok)
{
string text = File.ReadAllText(dialog.FileName);
}
}

Получившийся текст я могу вывести на экран через FileTxt.Text. Напомню, что FileTxt называется мой TextBlock в интерфейсе.

Код с FileTxt.Text = text; подчёркнут

Итого наша программа, после выбора файла, будет выглядеть вот так.

В окне MainWindow отображается содержимое выбранного текстового файла

Выбор папки

Однако, что если я хочу выбрать не файл, а папку? Мы можем настроить CommonOpenFileDialog для открытия папки. Для этого при создании переменной вместо круглых скобок мы напишем фигурные. Внутри фигурных скобок есть свойство IsFolderPicker. Если мы хотим сделать диалоговое окно по выбору папок, то IsFolderPicker должен быть равен true.

private void OpenBtn_Click(object sender, RoutedEventArgs e)
{
CommonOpenFileDialog dialog = new CommonOpenFileDialog { IsFolderPicker = true };
}

Вся остальная работа с папками будет такая же: отображаем диалоговое окно с помощью ShowDialog(), результат окна сохраняем в переменную result. Если мы хотим быть уверены, что папка была выбрана, нам нужно условие if (result == CommonFileDialogResult.Ok). Внутри мы уже будем читать полный путь до папки, например, давайте прочитаем все файлы из этой папки и выведем их в текстовое поле. Путь до выбранной папки мы также будем брать через свойство FileName.

private void OpenBtn_Click(object sender, RoutedEventArgs e)
{
CommonOpenFileDialog dialog = new CommonOpenFileDialog { IsFolderPicker = true };
var result = dialog.ShowDialog(); // открываем окошко
if (result == CommonFileDialogResult.Ok)
{
string[] files = Directory.GetFiles(dialog.FileName); // получаем все файлы из папки
foreach (string file in files) // перебираем файлы
{
FileTxt.Text += file + "\n"; // чтобы каждый новый файл был с новой строчки
}
}
}

По итогу у нас будет открываться выбор папки, а не файла.

Диалог выбора папки на рабочем столе

И как только мы выберем какую-то папку, то все файлы из этой папки будут выведены в интерфейс.

Список путей до файлов в выбранной папке выведен в TextBlock

Полный код примера

MainWindow.xaml.cs с двумя вариантами CommonOpenFileDialog — для файла и для папки:

using System.IO;
using System.Windows;
using Microsoft.WindowsAPICodePack.Dialogs;
namespace WpfApp1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
// Выбор файла
private void OpenFileBtn_Click(object sender, RoutedEventArgs e)
{
CommonOpenFileDialog dialog = new CommonOpenFileDialog();
CommonFileDialogResult result = dialog.ShowDialog();
if (result == CommonFileDialogResult.Ok)
{
string text = File.ReadAllText(dialog.FileName);
FileTxt.Text = text;
}
}
// Выбор папки
private void OpenFolderBtn_Click(object sender, RoutedEventArgs e)
{
CommonOpenFileDialog dialog = new CommonOpenFileDialog { IsFolderPicker = true };
CommonFileDialogResult result = dialog.ShowDialog();
if (result == CommonFileDialogResult.Ok)
{
string[] files = Directory.GetFiles(dialog.FileName);
foreach (string file in files)
{
FileTxt.Text += file + "\n";
}
}
}
}
}
просмотров