将过滤器设置为 OpenFileDialog 以允许典型的图像格式?

Posted

技术标签:

【中文标题】将过滤器设置为 OpenFileDialog 以允许典型的图像格式?【英文标题】:Setting the filter to an OpenFileDialog to allow the typical image formats? 【发布时间】:2011-01-05 08:35:53 【问题描述】:

我有这个代码,我怎样才能让它接受所有典型的图像格式? 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,但其他类型呢?

【问题讨论】:

【参考方案1】:

来自the docs,您需要的过滤器语法如下:

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

即用分号分隔多个扩展名 - 因此,Image Files|*.jpg;*.jpeg;*.png;...

【讨论】:

【参考方案2】:

这是 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("012 (3)|3", ofd.Filter, sep, codecName, c.FilenameExtension)
            sep = "|"
        Next
        ofd.Filter = String.Format("012 (3)|3", ofd.Filter, sep, "All Files", "*.*")

它看起来像这样:

【讨论】:

这种方法的好处:它将跟上任何将来向 .NET 添加支持的图像类型。谢谢 我非常喜欢这个,我已经把它变成了世界上最恶心的单线! 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") 啊,是的。 VB,我有时会想你 不使用Substring(x)获取codecName如下:string codecName = string.Format("0 files", c.FormatDescription);【参考方案3】:

完整的 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("012 (3)|3", dlg.Filter, sep, codecName, c.FilenameExtension);
       sep = "|";
    

    dlg.Filter = String.Format("012 (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  
    
 

【讨论】:

【参考方案4】:

要过滤图像文件,请使用此代码示例。

//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
   ....

【讨论】:

【参考方案5】:

我最喜欢 Tom Faust 的回答。这是他的解决方案的 C# 版本,但稍微简化了一点。

var codecs = ImageCodecInfo.GetImageEncoders(); 
var codecFilter = "Image Files|"; 
foreach (var codec in codecs) 

    codecFilter += codec.FilenameExtension + ";"; 
 
dialog.Filter = codecFilter;

【讨论】:

【参考方案6】:

对于图像,您可以从 GDI (System.Drawing) 获取可用的编解码器,并通过一些工作来构建您的列表。这将是最灵活的方式。

ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();

【讨论】:

感谢您的提示!我添加了这些,它就像一个魅力:var imageExtensions = string.Join(";", ImageCodecInfo.GetImageDecoders().Select(ici =&gt; ici.FilenameExtension));dialog.Filter = string.Format("Images|0|All Files|*.*", imageExtensions); 呃...不确定如何在评论中执行多行代码块:| 不是原作者:)【参考方案7】:

只是一个关于使用 string.Join 和 LINQ 的 necrocomment。

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

【讨论】:

【参考方案8】:

对于那些不想每次都记住语法的人来说,这里是一个简单的封装:

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

【讨论】:

【参考方案9】:

为了匹配一个不同类别的文件列表,你可以像这样使用过滤器:

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

【讨论】:

【参考方案10】:

这很极端,但我使用名为 FILE_TYPES 的 2 列数据库表构建了一个动态的、数据库驱动的过滤器,字段名称为 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];
            ...

应该产生一个看起来像这样的过滤器:

【讨论】:

投反对票,想解释一下吗?你有更好的主意吗?我的作品,正如我通过图形展示的那样。 Filter="Document files (*.doc,*.docx,*.pdf)|*.doc;*.docx,*.pdf|Image files (*.bmp,*.jpg)|*.bmp;*.jpg"; 这应该会产生一个看起来像上面答案中的最后一张图片的过滤器。 @mjb 如果您查看我的答案,您会发现我已经在代码顶部的注释中找到了答案。如果它不起作用,我就没有图形来证明它起作用了。正如我所解释的,代码从数据库表中获取值并将它们连接起来。您只需将 Doctype(“Documents”、“Images”等)和 Extension 作为 2 列放在名为“FILE_TYPES”的表上。假设您有一个名为DataLayer.Get_DataTable() 的函数,它将接受我在此代码中的 SQL 命令并将数据表发回给您,它会为您做所有事情。正如我所说,是的,这是极端的,但它确实有效。 是的。但是他们……你的帖子中只有 10% 是对这个问题的直接回答。其他 90% 是解决问题所不需要的额外信息。该问题不要求有关从数据库获取数据的信息,也没有询问连接...和bla...bla...bla....还有一些SQL命令? ...数据表?为什么不包括从 Web 服务中提取数据……并演示 JSON 字符串解析……或 XML 数据转换以获取文件类型?还有来自 NoSQL?以及从前端到后端的文件类型的 javascript 调用?....不...这超出了主题。 @mjb 点了,但这也是为了展示中间那个foreach 循环的力量。您可能有大量不同的文档类型,以及其中的扩展。这是一种组织它们的方式,然后应用代码来获取它们。对我来说,这比假设每个只有 3 个并给出连接字符串要好。教人钓鱼....【参考方案11】:

使用此方法返回从ImageCodecInfo 构建的过滤器兼容字符串,支持当前系统理解的图像格式。

        /// <summary>
        /// Get the Filter string for all supported image types.
        /// To be used in the FileDialog class Filter Property.
        /// </summary>
        /// <returns></returns>
        public static string GetImageFilter()
        
            string imageExtensions = string.Empty;
            string separator = "";
            ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
            Dictionary<string, string> imageFilters = new Dictionary<string, string>();
            foreach (ImageCodecInfo codec in codecs)
            
                imageExtensions = $"imageExtensionsseparatorcodec.FilenameExtension.ToLower()";
                separator = ";";
                imageFilters.Add($"codec.FormatDescription files (codec.FilenameExtension.ToLower())", codec.FilenameExtension.ToLower());
            
            string result = string.Empty;
            separator = "";
            foreach (KeyValuePair<string, string> filter in imageFilters)
            
                result += $"separatorfilter.Key|filter.Value";
                separator = "|";
            
            if (!string.IsNullOrEmpty(imageExtensions))
            
                result += $"separatorImage files|imageExtensions";
            
            return result;
        

结果如图:

【讨论】:

【参考方案12】:

您必须包含所有图像类型扩展名并允许所有文件作为选项。

所有文件|.|所有图片|.jpg;.jpeg;.png;.gif;.tif; .bmp|JPEG 图片|.jpg|PNG 图片|.png";

【讨论】:

以上是关于将过滤器设置为 OpenFileDialog 以允许典型的图像格式?的主要内容,如果未能解决你的问题,请参考以下文章

Win32 OpenFileDialog 不过滤 *.DOCX 快捷方式

在 OpenFileDialog 中过滤文件的正则表达式

OpenFileDialog C# 自定义过滤器,例如 'ABC*.pdf'

C# - 如何在 OpenFileDialog 中允许多种文件类型?

自定义 TreeView 以允许多选

C# 如何处理 OpenFileDialog 文件