Ustawienie filtru na OpenFileDialog, aby umożliwić typowe formaty obrazów?

229

Mam ten kod. Jak mogę pozwolić, aby akceptował wszystkie typowe formaty obrazów? PNG, JPEG, JPG, GIF?

Oto co mam do tej pory:

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

Zauważ, że filtr ustawiony jest na pliki .txt. I mogłaby zmienić PNG, ale co z innymi typami?

Sergio Tapia
źródło

Odpowiedzi:

289

Z dokumentów potrzebna jest następująca składnia filtra:

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

tzn. oddziel wiele rozszerzeń średnikiem - w ten sposób Image Files|*.jpg;*.jpeg;*.png;....

itowlson
źródło
179

Postępuj zgodnie z tym wzorem, jeśli przeglądasz pliki obrazów:

dialog.Filter =  "Image files (*.jpg, *.jpeg, *.jpe, *.jfif, *.png) | *.jpg; *.jpeg; *.jpe; *.jfif; *.png";
Devam Mehta
źródło
6
Prawdopodobnie chcesz pozbyć się spacji przed i po znaku fajki oraz między średnikiem i gwiazdką w części filtrującej. Ale dobrze, inaczej.
vapcguy
W ten sposób można również zgrupować dowolny typ pliku. Miły!
Alper
74

Oto przykład sugestii ImageCodecInfo (w 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", "*.*")

I wygląda to tak:

wprowadź opis zdjęcia tutaj

Tom Faust
źródło
Korzyści z tego podejścia: będzie nadążać za wszelkimi przyszłymi dodatkami obsługiwanych typów obrazów do .NET. Dzięki
UuDdLrLrSs
Uwielbiam to tak bardzo, że przekształciłem go w najbardziej obrzydliwy jednoliniowy na świecie! 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}")}O tak. VB, czasami za tobą tęsknię
Westonsupermare
46

Kompletne rozwiązanie w C # jest tutaj:

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  
    }
} 
Deweloper
źródło
23

Aby filtrować pliki obrazów, użyj tego przykładu kodu.

//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
źródło
14

Najbardziej podoba mi się odpowiedź Toma Fausta. Oto jego rozwiązanie w wersji C #, ale nieco upraszczające.

var codecs = ImageCodecInfo.GetImageEncoders(); 
var codecFilter = "Image Files|"; 
foreach (var codec in codecs) 
{
    codecFilter += codec.FilenameExtension + ";"; 
} 
dialog.Filter = codecFilter;
NielW
źródło
11

W przypadku obrazów możesz pobrać dostępne kodeki z GDI (System.Drawing) i zbudować z tego swoją listę przy odrobinie pracy. To byłby najbardziej elastyczny sposób.

ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
Muad'Dib
źródło
5
Dzięki za tę wskazówkę! Dodałem je i zadziałało to jak urok: var imageExtensions = string.Join(";", ImageCodecInfo.GetImageDecoders().Select(ici => ici.FilenameExtension)); dialog.Filter = string.Format("Images|{0}|All Files|*.*", imageExtensions);
Atlantis
ugh ... nie jestem pewien, jak zrobić wielowierszowe bloki kodu w komentarzu: |
atlantis
1
Nie oryginalny autor :)
atlantis,
9

Po prostu nekrolog za używanie string.Join i 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
źródło
4

Dla tych, którzy nie chcą pamiętać składni za każdym razem, dostępna jest prosta enkapsulacja:

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

Stosowanie:

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
źródło
3

Aby dopasować listę różnych kategorii plików, możesz użyć takiego filtra:

        var dlg = new Microsoft.Win32.OpenFileDialog()
        {
            DefaultExt = ".xlsx",
            Filter = "Excel Files (*.xls, *.xlsx)|*.xls;*.xlsx|CSV Files (*.csv)|*.csv"
        };
Kreshnik
źródło
1

Jest to ekstremalne, ale zbudowałem dynamiczny, oparty na bazie danych filtr, używając 2-kolumnowej tabeli bazy danych o nazwie FILE_TYPES, z nazwami pól EXTENSION i DOCTYPE:

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

Oczywiście miałem wiele różnych typów i rozszerzeń, ale upraszczam to w tym przykładzie. Oto moja funkcja:

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

Powinien dać filtr, który wygląda następująco:

wprowadź opis zdjęcia tutaj

vapcguy
źródło
Downvoter, chcesz wyjaśnić? Masz lepszy pomysł? Mój działa, jak pokazałem za pomocą grafiki.
vapcguy
2
Filter="Document files (*.doc,*.docx,*.pdf)|*.doc;*.docx,*.pdf|Image files (*.bmp,*.jpg)|*.bmp;*.jpg";i powinno to dać filtr, który wygląda jak ostatni obrazek w powyższej odpowiedzi.
mjb
@mjb Jeśli spojrzysz na moją odpowiedź, zobaczysz, że mam ją już w komentarzu u góry kodu. Gdyby to nie zadziałało, nie miałbym grafiki, która by to udowodniła. Jak wyjaśniłem, kod pobiera wartości z tabeli bazy danych i łączy je. Wystarczy umieścić Doctype („Dokumenty”, „Obrazy” itd.) I Rozszerzenie jako 2 kolumny w tabeli o nazwie „FILE_TYPES”. Zakładając, że masz wywoływaną funkcję DataLayer.Get_DataTable(), która pobierze polecenia SQL, które mam w tym kodzie i odeśle ci DataTable, zrobi to wszystko za Ciebie. Tak jak powiedziałem, tak, był ekstremalny, ale działa.
vapcguy
Tak. ale em ... tylko 10% twojego posta jest bezpośrednią odpowiedzią na pytanie. Pozostałe 90% to dodatkowe informacje, które nie są konieczne do rozwiązania pytania. Pytanie nie żąda informacji o pobieraniu danych z bazy danych i nie pyta o konkatenaty ... i bla ... bla ... bla .... kilka innych poleceń SQL? ... Tabela danych? Dlaczego nie uwzględnisz również pobierania danych z usług WWW ... i demonstrowania parsowania ciągów JSON ... lub konwersji danych XML, aby uzyskać typy plików? a także z NoSQL? i JavaScript wywołujący od front-end do back-end dla typów plików? .... nie ... to nie jest temat.
mjb
@mjb Punkt zajęty, ale ma także na celu zademonstrowanie mocy tej foreachpętli w środku. Możesz mieć TONY różnych rodzajów dokumentów i ich rozszerzenia. Służyło to jako sposób na ich uporządkowanie, a następnie zastosowanie kodu w celu ich uzyskania. Dla mnie było to lepsze niż zakładanie tylko 3 z nich i podawanie łańcucha konkatenacji. Naucz człowieka łowić ryby ...
vapcguy