Définir le filtre sur un OpenFileDialog pour autoriser les formats d'image typiques?

229

J'ai ce code, comment puis-je lui permettre d'accepter tous les formats d'image typiques? PNG, JPEG, JPG, GIF?

Voici ce que j'ai jusqu'à présent:

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. :)
    }             
}

Notez que le filtre est défini sur des fichiers .txt. Je pourrais changer en PNG, mais qu'en est-il des autres types?

Sergio Tapia
la source

Réponses:

289

À partir des documents , la syntaxe de filtre dont vous avez besoin est la suivante:

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

-à- dire séparer les multiples extensions par un point virgule - ainsi Image Files|*.jpg;*.jpeg;*.png;....

itowlson
la source
179

Suivez ce modèle si vous recherchez des fichiers image:

dialog.Filter =  "Image files (*.jpg, *.jpeg, *.jpe, *.jfif, *.png) | *.jpg; *.jpeg; *.jpe; *.jfif; *.png";
Devam Mehta
la source
6
Vous voulez probablement vous débarrasser des espaces avant et après le caractère pipe et entre le point-virgule et l'astérisque dans la partie filtre. Mais bon, sinon.
vapcguy
Vous pouvez également regrouper n'importe quel type de fichier de cette façon. Agréable!
Alper
74

Voici un exemple de la suggestion ImageCodecInfo (en 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", "*.*")

Et cela ressemble à ceci:

entrez la description de l'image ici

Tom Faust
la source
Avantage de cette approche: elle se tiendra au courant des futurs ajouts de types d'images pris en charge à .NET. Merci
UuDdLrLrSs
J'adore tellement cela que je l'ai converti en une doublure la plus dégoûtante du monde! 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}")}Ah oui. VB, tu me manques parfois
Westonsupermare
46

La solution complète en C # est ici:

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  
    }
} 
Développeur
la source
23

Pour filtrer les fichiers d'images, utilisez cet exemple de code.

//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
la source
14

J'aime mieux la réponse de Tom Faust. Voici une version C # de sa solution, mais simplifiant un peu les choses.

var codecs = ImageCodecInfo.GetImageEncoders(); 
var codecFilter = "Image Files|"; 
foreach (var codec in codecs) 
{
    codecFilter += codec.FilenameExtension + ";"; 
} 
dialog.Filter = codecFilter;
NielW
la source
11

Pour les images, vous pouvez obtenir les codecs disponibles à partir de GDI (System.Drawing) et construire votre liste à partir de cela avec un peu de travail. Ce serait la façon la plus flexible de procéder.

ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
Muad'Dib
la source
5
Merci pour cette astuce! J'ai ajouté ceux-ci et cela a fonctionné comme un charme: var imageExtensions = string.Join(";", ImageCodecInfo.GetImageDecoders().Select(ici => ici.FilenameExtension)); dialog.Filter = string.Format("Images|{0}|All Files|*.*", imageExtensions);
atlantis
ugh ... je ne sais pas comment faire des blocs de code multi-lignes dans un commentaire: |
atlantis
1
Pas l'auteur original :)
atlantis
9

Juste un nécrocomment pour utiliser string.Join et 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()));
Anthony L. Gershman
la source
4

Pour ceux qui ne veulent pas se souvenir de la syntaxe à chaque fois, voici une simple encapsulation:

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()));
    }
}

Usage:

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();
Yusuf Tarık Günaydın
la source
3

Afin de faire correspondre une liste de différentes catégories de fichiers, vous pouvez utiliser le filtre comme ceci:

        var dlg = new Microsoft.Win32.OpenFileDialog()
        {
            DefaultExt = ".xlsx",
            Filter = "Excel Files (*.xls, *.xlsx)|*.xls;*.xlsx|CSV Files (*.csv)|*.csv"
        };
Kreshnik
la source
1

C'est extrême, mais j'ai construit un filtre dynamique basé sur une base de données en utilisant une table de base de données à 2 colonnes nommée FILE_TYPES, avec les noms de champ EXTENSION et DOCTYPE:

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

Évidemment, j'avais de nombreux types et extensions différents, mais je le simplifie pour cet exemple. Voici ma fonction:

    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];
            ...

Devrait produire un filtre qui ressemble à ceci:

entrez la description de l'image ici

vapcguy
la source
Downvoter, souciez-vous d'expliquer? Vous avez une meilleure idée? Le mien fonctionne, comme je l'ai démontré à travers un graphique.
vapcguy
2
Filter="Document files (*.doc,*.docx,*.pdf)|*.doc;*.docx,*.pdf|Image files (*.bmp,*.jpg)|*.bmp;*.jpg";et cela devrait produire un filtre qui ressemble à la dernière image de la réponse ci-dessus.
mjb
@mjb Si vous regardiez ma réponse, vous verriez que je l'avais déjà dans le commentaire en haut du code. Si cela ne fonctionnait pas, je n'aurais pas le graphique pour le prouver. Comme je l'ai expliqué, le code prend des valeurs d'une table de base de données et les concatène. Vous mettriez simplement le Doctype ("Documents", "Images", etc.) et l'extension en 2 colonnes sur une table appelée "FILE_TYPES". En supposant que vous ayez appelé une fonction DataLayer.Get_DataTable()qui prendrait les commandes SQL que j'ai dans ce code et vous renverrait un DataTable, il ferait tout pour vous. Comme je l'ai dit, oui, c'était extrême, mais ça marche.
vapcguy
Oui. mais em ... seulement 10% de votre message est la réponse directe à la question. 90% sont des informations supplémentaires qui ne sont pas nécessaires pour résoudre la question. La question ne demande pas d'informations sur l'obtention de données de la base de données et n'a pas posé de questions sur les concaténations ... et bla ... bla ... bla .... quelques commandes SQL supplémentaires? ... DataTable? Pourquoi ne pas inclure également l'extraction de données des services Web ... et démontrer l'analyse de chaîne JSON ... ou la conversion de données XML pour obtenir les types de fichiers? et aussi de NoSQL? et Javascript appelant de l'avant vers l'arrière pour les types de fichiers? .... non ... cela est hors du sujet.
mjb
@mjb Point pris, mais c'est aussi pour démontrer la puissance de cette foreachboucle au milieu. Vous pouvez avoir des tonnes de doctypes différents et des extensions en leur sein. Cela a servi à les organiser, puis à appliquer du code pour les obtenir. Pour moi, c'était mieux que de simplement supposer qu'il n'y en avait que 3 de chaque et donner la chaîne de concaténation. Apprenez à un homme à pêcher ....
vapcguy