¿Establecer el filtro en un OpenFileDialog para permitir los formatos de imagen típicos?

229

Tengo este código, ¿cómo puedo permitir que acepte todos los formatos de imagen típicos? PNG, JPEG, JPG, GIF?

Esto es lo que tengo hasta ahora:

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

Observe que el filtro está configurado en archivos .txt. Yo podría cambiar a PNG, pero lo de los otros tipos?

Sergio Tapia
fuente

Respuestas:

289

De los documentos , la sintaxis de filtro que necesita es la siguiente:

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

es decir, separan las múltiples extensiones con un punto y coma - por lo tanto, Image Files|*.jpg;*.jpeg;*.png;....

itowlson
fuente
179

Siga este patrón si está buscando archivos de imagen:

dialog.Filter =  "Image files (*.jpg, *.jpeg, *.jpe, *.jfif, *.png) | *.jpg; *.jpeg; *.jpe; *.jfif; *.png";
Devam Mehta
fuente
66
Probablemente quiera deshacerse de los espacios antes y después del carácter de la tubería y entre el punto y coma y el asterisco en la parte del filtro. Pero bueno, de lo contrario.
vapcguy
También puede agrupar cualquier tipo de archivo de esta manera. ¡Agradable!
Alper
74

Aquí hay un ejemplo de la sugerencia 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", "*.*")

Y se ve así:

ingrese la descripción de la imagen aquí

Tom Faust
fuente
Beneficio de este enfoque: se mantendrá al día con cualquier futura incorporación de tipos de imágenes compatibles a .NET. Gracias
UuDdLrLrSs
¡Me encanta tanto que lo he convertido en la frase más repugnante del mundo! 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, sí. VB, a veces te extraño
Westonsupermare
46

La solución completa en C # está aquí:

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  
    }
} 
Desarrollador
fuente
23

Para filtrar archivos de imágenes, use este ejemplo de código.

//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
fuente
14

Me gusta la respuesta de Tom Faust mejor. Aquí hay una versión C # de su solución, pero simplificando un poco las cosas.

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

Para las imágenes, puede obtener los códecs disponibles de GDI (System.Drawing) y construir su lista a partir de eso con un poco de trabajo. Esta sería la forma más flexible de hacerlo.

ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
Muad'Dib
fuente
55
Gracias por este consejo! Agregué estos y funcionó de maravilla: var imageExtensions = string.Join(";", ImageCodecInfo.GetImageDecoders().Select(ici => ici.FilenameExtension)); dialog.Filter = string.Format("Images|{0}|All Files|*.*", imageExtensions);
atlantis
ugh ... no estoy seguro de cómo hacer bloques de código de varias líneas en un comentario: |
atlantis
1
No es el autor original :)
atlantis
9

Solo un comentario negativo para usar string.Join y 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
fuente
4

Para aquellos que no quieren recordar la sintaxis cada vez, aquí hay una simple encapsulación:

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

Uso:

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
fuente
3

Para hacer coincidir una lista de diferentes categorías de archivos, puede usar el filtro de esta manera:

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

Esto es extremo, pero construí un filtro dinámico basado en una base de datos usando una tabla de base de datos de 2 columnas llamada FILE_TYPES, con los nombres de campo EXTENSION y DOCTYPE:

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

Obviamente tenía muchos tipos y extensiones diferentes, pero lo estoy simplificando para este ejemplo. Aquí está mi función:

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

Debería producir un filtro que se vea así:

ingrese la descripción de la imagen aquí

vapcguy
fuente
Downvoter, ¿quieres explicarlo? Tienes una mejor idea? El mío funciona, como lo demostré a través de un gráfico.
vapcguy
2
Filter="Document files (*.doc,*.docx,*.pdf)|*.doc;*.docx,*.pdf|Image files (*.bmp,*.jpg)|*.bmp;*.jpg";y esto debería producir un filtro que se parece a la última imagen en la respuesta anterior.
mjb
@mjb Si miraras mi respuesta, verías que ya la tenía en el comentario en la parte superior del código. Si no funcionara, no tendría el gráfico para demostrar que sí. Como expliqué, el código toma valores de una tabla de base de datos y los concatena. Simplemente colocaría el Doctype ("Documentos", "Imágenes", etc.) y la Extensión como 2 columnas en una tabla llamada "FILE_TYPES". Asumiendo que tenía una función llamada DataLayer.Get_DataTable()que tomaría los comandos SQL que tengo en este código y le devolvería una DataTable, haría todo por usted. Como dije, sí, fue extremo, pero funciona.
vapcguy
Si. pero em ... solo el 10% de tu publicación es la respuesta directa a la pregunta. Otro 90% es información adicional que no es necesaria para resolver la pregunta. La pregunta no solicita información sobre cómo obtener datos de la base de datos y no pregunta sobre concatenados ... y bla ... bla ... bla ... ¿hay más comandos SQL? ... ¿Tabla de datos? ¿Por qué no incluye también extraer datos de los servicios web ... y demostrar el análisis de cadenas JSON ... o la conversión de datos XML para obtener tipos de archivos? y también de NoSQL? y Javascript llamando de front-end a back-end para los Tipos de archivo? .... no ... eso está fuera del tema.
mjb
@mjb Punto tomado, pero también es para demostrar el poder de ese foreachbucle en el medio. Es posible que tenga TONELADAS de diferentes tipos de documentos y extensiones dentro de ellos. Esto sirvió como una forma de organizarlos, luego aplicar código para obtenerlos. Para mí, fue mejor que simplemente asumir que solo había 3 de cada uno y dar la cadena de concatenación. Enseñar a un hombre a pescar ....
vapcguy