Setzen Sie den Filter auf einen OpenFileDialog, um die typischen Bildformate zuzulassen?

229

Ich habe diesen Code. Wie kann ich zulassen, dass alle typischen Bildformate akzeptiert werden? PNG, JPEG, JPG, GIF?

Folgendes habe ich bisher:

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

Beachten Sie, dass der Filter auf TXT-Dateien eingestellt ist. Ich könnte zu PNG wechseln, aber was ist mit den anderen Typen?

Sergio Tapia
quelle

Antworten:

289

In den Dokumenten ist folgende Filtersyntax erforderlich:

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

dh trennen Sie die mehreren Erweiterungen mit einem Semikolon - also , Image Files|*.jpg;*.jpeg;*.png;....

itowlson
quelle
179

Folgen Sie diesem Muster, wenn Sie nach Bilddateien suchen:

dialog.Filter =  "Image files (*.jpg, *.jpeg, *.jpe, *.jfif, *.png) | *.jpg; *.jpeg; *.jpe; *.jfif; *.png";
Devam Mehta
quelle
6
Wahrscheinlich möchten Sie die Leerzeichen vor und nach dem Pipe-Zeichen sowie zwischen dem Semikolon und dem Sternchen im Filterbereich entfernen. Aber sonst gut.
Vapcguy
Auf diese Weise können Sie auch einen beliebigen Dateityp gruppieren. Nett!
Alper
74

Hier ist ein Beispiel für den ImageCodecInfo-Vorschlag (in 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", "*.*")

Und es sieht so aus:

Geben Sie hier die Bildbeschreibung ein

Tom Faust
quelle
Vorteil dieses Ansatzes: Er wird mit zukünftigen Ergänzungen unterstützter Bildtypen zu .NET Schritt halten. Danke
UuDdLrLrSs
Ich liebe das so sehr, dass ich es zum ekelhaftesten Einzeiler der Welt gemacht habe! 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 ja. VB, ich vermisse dich manchmal
Westonsupermare
46

Die vollständige Lösung in C # finden Sie hier:

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  
    }
} 
Entwickler
quelle
23

Verwenden Sie dieses Codebeispiel, um Bilddateien zu filtern.

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

Die Antwort von Tom Faust gefällt mir am besten. Hier ist eine C # -Version seiner Lösung, die die Dinge jedoch ein wenig vereinfacht.

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

Für Bilder können Sie die verfügbaren Codecs von GDI (System.Drawing) herunterladen und mit ein wenig Arbeit Ihre Liste daraus erstellen. Dies wäre der flexibelste Weg.

ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
Muad'Dib
quelle
5
Danke für diesen Tipp! Ich fügte diese hinzu und es funktionierte wie ein Zauber: var imageExtensions = string.Join(";", ImageCodecInfo.GetImageDecoders().Select(ici => ici.FilenameExtension)); dialog.Filter = string.Format("Images|{0}|All Files|*.*", imageExtensions);
Atlantis
ugh ... nicht sicher, wie man mehrzeilige Codeblöcke in einem Kommentar macht: |
Atlantis
1
Nicht der ursprüngliche Autor :)
Atlantis
9

Nur ein Nekrokommentar für die Verwendung von string.Join und 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
quelle
4

Für diejenigen, die sich nicht jedes Mal an die Syntax erinnern möchten, ist hier eine einfache Kapselung:

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

Verwendung:

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

Um eine Liste verschiedener Dateikategorien abzugleichen, können Sie den Filter folgendermaßen verwenden:

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

Das ist extrem, aber ich habe einen dynamischen, datenbankgesteuerten Filter mit einer zweispaltigen Datenbanktabelle namens FILE_TYPES mit den Feldnamen EXTENSION und DOCTYPE erstellt:

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

Natürlich hatte ich viele verschiedene Typen und Erweiterungen, aber ich vereinfache es für dieses Beispiel. Hier ist meine Funktion:

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

Sollte einen Filter ergeben, der so aussieht:

Geben Sie hier die Bildbeschreibung ein

vapcguy
quelle
Downvoter, willst du das erklären? Du hast eine bessere Idee? Meins funktioniert, wie ich anhand einer Grafik demonstriert habe.
Vapcguy
2
Filter="Document files (*.doc,*.docx,*.pdf)|*.doc;*.docx,*.pdf|Image files (*.bmp,*.jpg)|*.bmp;*.jpg";und dies sollte einen Filter ergeben, der wie das letzte Bild in der obigen Antwort aussieht.
MJB
@mjb Wenn Sie sich meine Antwort ansehen, werden Sie sehen, dass ich das bereits im Kommentar oben im Code hatte. Wenn es nicht funktioniert hätte, hätte ich nicht die Grafik, um zu beweisen, dass es funktioniert. Wie ich erklärt habe, nimmt der Code Werte aus einer Datenbanktabelle und verkettet sie. Sie würden einfach den Doctype ("Dokumente", "Bilder" usw.) und die Erweiterung als 2 Spalten in eine Tabelle mit dem Namen "FILE_TYPES" einfügen. Angenommen, Sie hätten eine Funktion namens aufgerufen DataLayer.Get_DataTable(), die die in diesem Code enthaltenen SQL-Befehle übernimmt und Ihnen eine DataTable zurücksendet, würde sie alles für Sie tun. Wie gesagt, ja, war extrem, aber es funktioniert.
Vapcguy
Ja. aber em ... nur 10% Ihres Beitrags ist die direkte Antwort auf die Frage. Weitere 90% sind zusätzliche Informationen, die zur Lösung der Frage nicht erforderlich sind. Die Frage fordert keine Informationen zum Abrufen von Daten aus der Datenbank an und fragt nicht nach Verkettungen ... und bla ... bla ... bla ... weiteren SQL-Befehlen? ... Datentabelle? Warum schließen Sie nicht auch das Abrufen von Daten aus Webdiensten ein ... und demonstrieren das Parsen von JSON-Zeichenfolgen ... oder die Konvertierung von XML-Daten, um Dateitypen abzurufen? und auch von NoSQL? und Javascript-Aufrufe vom Front-End zum Back-End für die Dateitypen? .... nein ... das ist nicht im Thema.
MJB
@mjb Punkt genommen, aber es ist auch, um die Kraft dieser foreachSchleife in der Mitte zu demonstrieren . Möglicherweise haben Sie TONNEN verschiedener Doctypes und Erweiterungen darin. Dies diente dazu, sie zu organisieren und dann Code anzuwenden, um sie zu erhalten. Für mich war es besser, als nur anzunehmen, dass es nur drei von jedem gab und die Verkettungszeichenfolge anzugeben.
Bringen Sie