将过滤器设置为 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 => 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 C# 自定义过滤器,例如 'ABC*.pdf'