Установка фильтра для OpenFileDialog, чтобы разрешить типичные форматы изображений?

229

У меня есть этот код, как я могу позволить ему принимать все типичные форматы изображений? PNG, JPEG, JPG, GIF?

Вот что у меня так далеко:

public void EncryptFile()
{            
    OpenFileDialog dialog = new OpenFileDialog();
    dialog.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";
    dialog.InitialDirectory = @"C:\";
    dialog.Title = "Please select an image file to encrypt.";

    if (dialog.ShowDialog() == DialogResult.OK)
    {
        //Encrypt the selected file. I'll do this later. :)
    }             
}

Обратите внимание, что фильтр настроен на файлы .txt. Я мог бы перейти на PNG, но что из других типов?

Серхио Тапиа
источник

Ответы:

289

Из документов , синтаксис фильтра, который вам нужен, выглядит следующим образом:

Office Files|*.doc;*.xls;*.ppt

то есть разделите несколько расширений точкой с запятой - таким образом Image Files|*.jpg;*.jpeg;*.png;....

itowlson
источник
179

Следуйте этой схеме, если вы просматриваете файлы изображений:

dialog.Filter =  "Image files (*.jpg, *.jpeg, *.jpe, *.jfif, *.png) | *.jpg; *.jpeg; *.jpe; *.jfif; *.png";
Девам Мехта
источник
6
Вероятно, хотите избавиться от пробелов до и после символа канала, а также между точкой с запятой и звездочкой в ​​части фильтра. Но хорошо, иначе.
vapcguy
Вы также можете сгруппировать любой тип файла с этим способом. Ницца!
Alper
74

Вот пример предложения ImageCodecInfo (в VB):

   Imports System.Drawing.Imaging
        ...            

        Dim ofd as new OpenFileDialog()
        ofd.Filter = ""
        Dim codecs As ImageCodecInfo() = ImageCodecInfo.GetImageEncoders()
        Dim sep As String = String.Empty
        For Each c As ImageCodecInfo In codecs
            Dim codecName As String = c.CodecName.Substring(8).Replace("Codec", "Files").Trim()
            ofd.Filter = String.Format("{0}{1}{2} ({3})|{3}", ofd.Filter, sep, codecName, c.FilenameExtension)
            sep = "|"
        Next
        ofd.Filter = String.Format("{0}{1}{2} ({3})|{3}", ofd.Filter, sep, "All Files", "*.*")

И это выглядит так:

введите описание изображения здесь

Том Фауст
источник
Преимущество такого подхода: он будет идти в ногу со всеми будущими добавлениями поддерживаемых типов изображений в .NET. Спасибо
UuDdLrLrSs
Я люблю это так сильно, что превратил его в самую отвратительную однострочку в мире! Dim ofd As New OpenFileDialog() With {.Filter = ImageCodecInfo.GetImageEncoders().Aggregate("All Files (*.*)|*.*", Function(s, c) $"{s}|{c.CodecName.Substring(8).Replace("Codec", "Files").Trim()} ({c.FilenameExtension})|{c.FilenameExtension}")}О да. В.Б., я скучаю по тебе иногда
Westonsupermare
46

Полное решение в C # здесь:

private void btnSelectImage_Click(object sender, RoutedEventArgs e)
{
    // Configure open file dialog box 
    Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
    dlg.Filter = "";

    ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
    string sep = string.Empty;

    foreach (var c in codecs)
    {
       string codecName = c.CodecName.Substring(8).Replace("Codec", "Files").Trim();
       dlg.Filter = String.Format("{0}{1}{2} ({3})|{3}", dlg.Filter, sep, codecName, c.FilenameExtension);
       sep = "|";
    }

    dlg.Filter = String.Format("{0}{1}{2} ({3})|{3}", dlg.Filter, sep, "All Files", "*.*"); 

    dlg.DefaultExt = ".png"; // Default file extension 

    // Show open file dialog box 
    Nullable<bool> result = dlg.ShowDialog();

    // Process open file dialog box results 
    if (result == true)
    {
       // Open document 
       string fileName  = dlg.FileName;
       // Do something with fileName  
    }
} 
разработчик
источник
23

Для фильтрации файлов изображений используйте этот пример кода.

//Create a new instance of openFileDialog
OpenFileDialog res = new OpenFileDialog();

//Filter
res.Filter = "Image Files|*.jpg;*.jpeg;*.png;*.gif;*.tif;...";

//When the user select the file
if (res.ShowDialog() == DialogResult.OK)
{
   //Get the file's path
   var filePath = res.FileName;
   //Do something
   ....
}
HermF
источник
14

Мне больше нравится ответ Тома Фауста. Вот версия C # его решения, но немного упрощающая.

var codecs = ImageCodecInfo.GetImageEncoders(); 
var codecFilter = "Image Files|"; 
foreach (var codec in codecs) 
{
    codecFilter += codec.FilenameExtension + ";"; 
} 
dialog.Filter = codecFilter;
NielW
источник
11

Для изображений вы можете получить доступные кодеки из GDI (System.Drawing) и построить свой список из этого с небольшой работой. Это был бы самый гибкий путь.

ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
Муад'Диб
источник
5
Спасибо за этот совет! Я добавил их, и это сработало как очарование: var imageExtensions = string.Join(";", ImageCodecInfo.GetImageDecoders().Select(ici => ici.FilenameExtension)); dialog.Filter = string.Format("Images|{0}|All Files|*.*", imageExtensions);
atlantis
тьфу ... не уверен, как сделать блоки многострочного кода в комментарии: |
Атлантида
1
Не оригинальный автор :)
atlantis
9

Просто некроммент для использования string.Join и LINQ.

ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
dlgOpenMockImage.Filter = string.Format("{0}| All image files ({1})|{1}|All files|*", 
    string.Join("|", codecs.Select(codec => 
    string.Format("{0} ({1})|{1}", codec.CodecName, codec.FilenameExtension)).ToArray()),
    string.Join(";", codecs.Select(codec => codec.FilenameExtension).ToArray()));
Энтони Л. Гершман
источник
4

Для тех, кто не хочет каждый раз вспоминать синтаксис, есть простая инкапсуляция:

public class FileDialogFilter : List<string>
{
    public string Explanation { get; }

    public FileDialogFilter(string explanation, params string[] extensions)
    {
        Explanation = explanation;
        AddRange(extensions);
    }

    public string GetFileDialogRepresentation()
    {
        if (!this.Any())
        {
            throw new ArgumentException("No file extension is defined.");
        }

        StringBuilder builder = new StringBuilder();

        builder.Append(Explanation);

        builder.Append(" (");
        builder.Append(String.Join(", ", this));
        builder.Append(")");

        builder.Append("|");
        builder.Append(String.Join(";", this));

        return builder.ToString();
    }
}

public class FileDialogFilterCollection : List<FileDialogFilter>
{
    public string GetFileDialogRepresentation()
    {
        return String.Join("|", this.Select(filter => filter.GetFileDialogRepresentation()));
    }
}

Использование:

FileDialogFilter filterImage = new FileDialogFilter("Image Files", "*.jpeg", "*.bmp");
FileDialogFilter filterOffice = new FileDialogFilter("Office Files", "*.doc", "*.xls", "*.ppt");

FileDialogFilterCollection filters = new FileDialogFilterCollection
{
    filterImage,
    filterOffice
};

OpenFileDialog fileDialog = new OpenFileDialog
{
    Filter = filters.GetFileDialogRepresentation()
};

fileDialog.ShowDialog();
Юсуф Тарык Гюнайдын
источник
3

Чтобы сопоставить список файлов разных категорий, вы можете использовать фильтр следующим образом:

        var dlg = new Microsoft.Win32.OpenFileDialog()
        {
            DefaultExt = ".xlsx",
            Filter = "Excel Files (*.xls, *.xlsx)|*.xls;*.xlsx|CSV Files (*.csv)|*.csv"
        };
Kreshnik
источник
1

Это экстремально, но я построил динамический фильтр на основе базы данных, используя таблицу базы данных из 2 столбцов с именем FILE_TYPES, с именами полей EXTENSION и DOCTYPE:

---------------------------------
| EXTENSION  |  DOCTYPE         |
---------------------------------
|   .doc     |  Document        |
|   .docx    |  Document        |
|   .pdf     |  Document        |
|   ...      |  ...             |
|   .bmp     |  Image           |
|   .jpg     |  Image           |
|   ...      |  ...             |
---------------------------------

Очевидно, у меня было много разных типов и расширений, но я упрощаю это для этого примера. Вот моя функция:

    private static string GetUploadFilter()
    {
        // Desired format:
        // "Document files (*.doc, *.docx, *.pdf)|*.doc;*.docx;*.pdf|"
        // "Image files (*.bmp, *.jpg)|*.bmp;*.jpg|"

        string filter = String.Empty;
        string nameFilter = String.Empty;
        string extFilter = String.Empty;

        // Used to get extensions
        DataTable dt = new DataTable();
        dt = DataLayer.Get_DataTable("SELECT * FROM FILE_TYPES ORDER BY EXTENSION");

        // Used to cycle through doctype groupings ("Images", "Documents", etc.)
        DataTable dtDocTypes = new DataTable();
        dtDocTypes = DataLayer.Get_DataTable("SELECT DISTINCT DOCTYPE FROM FILE_TYPES ORDER BY DOCTYPE");

        // For each doctype grouping...
        foreach (DataRow drDocType in dtDocTypes.Rows)
        {
            nameFilter = drDocType["DOCTYPE"].ToString() + " files (";

            // ... add its associated extensions
            foreach (DataRow dr in dt.Rows)
            {
                if (dr["DOCTYPE"].ToString() == drDocType["DOCTYPE"].ToString())
                {
                    nameFilter += "*" + dr["EXTENSION"].ToString() + ", ";
                    extFilter += "*" + dr["EXTENSION"].ToString() + ";";
                }                    
            }

            // Remove endings put in place in case there was another to add, and end them with pipe characters:
            nameFilter = nameFilter.TrimEnd(' ').TrimEnd(',');
            nameFilter += ")|";
            extFilter = extFilter.TrimEnd(';');
            extFilter += "|";

            // Add the name and its extensions to our main filter
            filter += nameFilter + extFilter;

            extFilter = ""; // clear it for next round; nameFilter will be reset to the next DOCTYPE on next pass
        }

        filter = filter.TrimEnd('|');
        return filter;
    }

    private void UploadFile(string fileType, object sender)
    {            
        Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
        string filter = GetUploadFilter();
        dlg.Filter = filter;

        if (dlg.ShowDialog().Value == true)
        {
            string fileName = dlg.FileName;

            System.IO.FileStream fs = System.IO.File.OpenRead(fileName);
            byte[] array = new byte[fs.Length];

            // This will give you just the filename
            fileName = fileName.Split('\\')[fileName.Split('\\').Length - 1];
            ...

Должен дать фильтр, который выглядит так:

введите описание изображения здесь

vapcguy
источник
Downvoter, хочешь объяснить? У тебя есть идея получше? Мои работы, как я продемонстрировал на графике.
vapcguy
2
Filter="Document files (*.doc,*.docx,*.pdf)|*.doc;*.docx,*.pdf|Image files (*.bmp,*.jpg)|*.bmp;*.jpg";и это должно привести к фильтру, который выглядит как последняя картинка в ответе выше.
MJB
@mjb Если вы посмотрите на мой ответ, вы увидите, что это уже было в комментарии в верхней части кода. Если бы это не сработало, у меня не было бы графика, чтобы доказать это. Как я объяснил, код берет значения из таблицы базы данных и объединяет их. Вы бы просто поместили Doctype («Документы», «Изображения» и т. Д.) И расширение в виде 2 столбцов таблицы с именем «FILE_TYPES». Предполагая, что у вас есть вызываемая функция, DataLayer.Get_DataTable()которая будет принимать команды SQL, которые есть в этом коде, и отправлять вам обратно таблицу данных, она все сделает за вас. Как я уже сказал, да, это было экстремально, но это работает.
vapcguy
Да. но эм ... только 10% вашего поста является прямым ответом на вопрос. Остальные 90% - это дополнительная информация, которая не нужна для решения вопроса. Вопрос не запрашивает информацию о получении данных из базы данных и не спрашивает о сцеплениях ... и бла ... бла ... бла ... еще несколько команд SQL? ... Таблица данных? Почему бы вам не включить извлечение данных из веб-служб ... и не продемонстрировать разбор строк JSON ... или преобразование данных XML для получения типов файлов? а также из NoSQL? и вызов Javascript от внешнего интерфейса к типам файлов? .... нет ... это не по теме.
MJB
@mjb Точка взята, но это также демонстрирует силу этого foreach цикла в середине. У вас могут быть ТОННЫ разных типов и расширения внутри них. Это послужило способом их организации, а затем применения кода для их получения. Для меня это было лучше, чем просто предполагать, что их было всего 3, и давать строку конкатенации. Научите человека ловить рыбу ....
vapcguy