Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

FilterBuilder

0.00/5 (No votes)
27 Oct 2009 1  
FilterBuilder is a simple utility allowing you to easily create dialog filters

Table of Contents

Introduction

FilterBuilder is a simple utility allowing you to easily create dialog filters. As well as containing 135 of the most common file filters, FilterBuilder allows you to create endless combinations of file filters without ever having to maintain lengthy filter strings.

Background

I wrote FilterBuilder because I did not like writing lengthy filter strings for every Open/Save dialog that I used. I needed a quick, easy way to add filters to the standard Open and Save File dialogs.

Some of my requirements were:

  • The utility had to have many preset filters.
  • The utility had to also accept custom filters.
  • The utility had to be able to add/remove filters easily.
  • The utility had to be able to generate a completed filter string.

Using the Code

To use the code, first add a reference to the FB.dll library. This is located in the Bin/Release folder.

Add an Imports statement as follows:

Imports FB

Create an instance of the FilterBuilder class. To add a filter, call the Add method of the instance, passing in either a value from the FilterBuilder.Filters enum or a custom filter as follows:

'Add a text files filter
FilterBuild.Add(FilterBuilder.Filters.TextFiles)

'Add a custom filter
FilterBuild.Add("Foo Files", "foo")

To remove a filter, call the Remove method:

'Remove rich text files filter
FilterBuild.Remove(FilterBuilder.Filters.RichTextFiles)

To get the completed filter string, call the ToString method:

'Get filter string
OpenFileDialog1.Filter = FilterBuild.ToString()

How It Works

The standard way to write a dialog filter is as follows:

"Plain Text Files (*.txt)|*.txt"

Whereas the same thing can be done in FilterBuilder like so:

FilterBuild.Add(FilterBuilder.Filters.TextFiles)

No doubt, the second example is much easier to use and also establishes consistency between different dialog boxes.

FilterBuilder uses a List(Of String) and a StringBuilder to keep track of the filters, and to return the complete filter string.

For the sake of simplicity, I chose not to make FilterBuilder inherit directly from List(Of T) but instead use it internally. I thought that List(Of T) exposed many more methods and properties than what FilterBuilder truly needed to operate.

All filters added through the Add method are added to the internal List, and conversely, filters removed through the Remove method are removed from the List.

Just a normal list. Simple eh?

If an enum value is passed to the Add method (see the Examples section for more information), that value is converted into a string value through the private ReturnFilterAsString method and then added to the List. If two string values are passed in, the filter string is built in the associated Add method, and added to the List.

The great part is actually getting the required filter string - for use in Open and Save File Dialogs. As mentioned in the "Using The Code" section, this is done through the ToString method. The ToString method uses a For Each loop to iterate over all the current items in the List(Of String) and concatenates each item with a "|" character. After this, the resulting string is trimmed of blank spaces (" ") and "|" characters at either end. The finished result is a filter string ready for use in Dialog Boxes!

FilterGroups

What on earth is a FilterGroup? Well I do not know if there is an official term for something that for instance looks like:

"Documents (*.html,*.rtf,*.txt)|*.html;*.rtf;*.txt"

... so I coined the term "FilterGroup".

As you can see above, this is a multiple item filter string that allows HTML, RTF, and TXT files to be displayed. This being FilterBuilder though, I wouldn't expect you to write out a lengthy filter string.

Here's the new way to achieve the same results as in the example above:

Dim docsGroup As New FilterGroup("Documents")

'Add the filters in this group
With docsGroup
	.Add(FilterBuilder.Filters.HTML_Files)
	.Add(FilterBuilder.Filters.RichTextFiles)
	.Add(FilterBuilder.Filters.TextFiles)
End With

Okay, let me explain what's happening.

  • The first line is creating a new instance of the FilterGroup class (which accepts one parameter - the name of the group).
  • The ".Add" statements are adding filters to the group. The Add statements are the same as those found in the FilterBuilder class, so you can pass in the same filters you would when using FilterBuilder normally.

So how does this tie into FilterBuilder itself?

FilterBuilder includes one extra Add method that takes a FilterGroup as its only parameter. So, that means that when you have finished creating your FilterGroup, you can pass it into FilterBuilder as follows:

FilterBuild.Add(docsGroup)

Summary

  • Create a FilterGroup with the name you wish to appear in the Open/Save dialog (e.g. "Documents").
  • Using the Add method of the group, add the filters that will be contained in this group.
  • Use the Add method of your FilterBuilder instance to add the FilterGroup to the main filter list.
  • Call the ToString method as normal to get the final filter string.

Note: For a more advanced example, please take a look at example #6 in the demo project download.

System File Types

If you still haven't been convinced about FilterBuilder by all that you have just read, I guarantee you that this will catch your attention.

System File Types - The ability to add dialog filters just by knowing the extension. No descriptions, No research, just a simple file extension.

So, this:

"dll"

becomes this:

"Application Extensions (*.dll)|*.dll"

Question: Okay, so how does that small extension turn into a full, internal filter string?

  • FilterBuilder obtains the correct description from the computer's registry. For this step, I used exactly the same method as outlined in Man Vuong's article here [^], and I suggest having a read through that.
  • After getting the description, FilterBuilder concatenates it with the extension adding in the "*", "." and "|" characters.

Question: How do I add a filter just by knowing its extension?

'Add the filter
FilterBuild.Add("dll")

Almost identical to how you would normally add a filter. Only, just pass in the string extension to the Add method.

Note: You can include a dot before the extension if you wish (e.g. ".dll" as opposed to "dll"). Either way will work.

Question: What about the optional plural parameter of the Add method?

'Add the filter (first way)
FilterBuild.Add("dll")

'Add the filter (second way)
FilterBuild.Add("dll", False)

When I first made the Filters enum I made the descriptions plural to account for the fact that many files could be selected. So, by default, when the System File Descriptions are retrieved from the registry, they are checked and modified to make sure that they are in plural form (i.e. "Files" instead of "File"). If you wish to not have these descriptions in plural form, pass in a "False" value as the second parameter of this overload of the Add method (as shown above).

Extra Info

You can get a list of all the System File Type extensions by calling the GetSystemFileTypes() method:

Dim l As List(Of String) = FilterBuild.GetSystemFileTypes()

Conclusion

System File Types are extremely useful when you do not know the description of an extension, or want it to be automatically updated when the value in the registry changes.

Summary

That's all there is to it!
Simply call the Add method - passing in the string extension of the file. If it is found on the user's system, it will be added to the filter string.

System File Type Icons

As a sort of follow-on from the topic above, this section explains about FilterBuilder's support for obtaining System File Type Icons for any file type contained in the computer registry.

Below is an example of how to get the file type icon of a preset filter (one from the FilterBuilder.Filters enum):

Dim icon As System.Drawing.Icon = _
FilterBuild.GetSystemFileTypeIcon( _
FilterBuilder.Filters.RichTextFiles)

Now is an example of how to get the file type icon of a system file type (one not contained in the enum):

Dim icon As System.Drawing.Icon = _
FilterBuild.GetSystemFileTypeIcon("rtf")

Note: The File Type Icons returned are (unsurprisingly) in Icon format but can be changed to a bitmap as shown in the full example below:

Full Example

'Declarations
Dim FilterBuild As New FilterBuilder()
Dim picIconView As New System.Windows.Forms.PictureBox()

'Get the icon for XML files
Dim icon As System.Drawing.Icon = _
FilterBuild.GetSystemFileTypeIcon( _
FilterBuilder.Filters.XML_Files)

'Convert icon to bitmap and set as image
picIconView.Image = icon.ToBitmap()

Extra Info

To change the size of the icon returned, you can modify the FileTypeIconSize property. It is either a 16x16px or a 32x32px icon.

Summary

That's all there is to it!
To get the associated system image for the file type, simply call the GetSystemFileTypeIcon method - passing in either a preset filter (from the Filters enum) or the string extension of the file type.

Custom Filters

A great feature of FilterBuilder is that not only does it allow you to use any combination of the preset filters, but it also allows you to include custom filters. This is especially useful if, like me, you use your own file types in your applications. Read on to find out how to add a custom filter in just one line of code...

As you have probably understood by now, filters are added through the overloaded Add method. One of these Add methods accepts two String parameters. Let's take the example below:

FilterBuild.Add("Foo Files", "foo")

In this example, I am adding a custom filter that will only allows files with the extension .foo to be displayed. This is the same as the string:

"Foo Files (*.foo)|*.foo"

Note: You can include a dot before the extension if you wish (e.g. ".foo" as opposed to "foo"). Either way will work.

Summary

That's all there is to it!
To add custom filters, simply call the Add method - passing in the description of the file, and the extension of the file.

Examples

Here are a few examples showing the methods available in FilterBuilder. More examples are contained in the attached "Demo project" download.

Note: If you wish, you can make an array of Filters and then just pass the array into the overloaded Add method. This is shown in the second example.

Example #1 -- A Text, RTF and HTML files filter:

'Declarations
Dim FilterBuild As New FilterBuilder()
Dim ofd As New OpenFileDialog()

'Add the filters
FilterBuild.Add(FilterBuilder.Filters.TextFiles)
FilterBuild.Add(FilterBuilder.Filters.RichTextFiles)
FilterBuild.Add(FilterBuilder.Filters.HTML_Files)

With ofd

	'Set the filter
	.Filter = FilterBuild.ToString()

	'Set filter index to the first item
	.FilterIndex = 1

	'Get the file extension of text files
	.DefaultExt = FilterBuild.GetFileExtension( _
	FilterBuilder.Filters.TextFiles)

	.ShowDialog()

End With

As you may have noticed in the above example, I used the GetFileExtension method - this returns the associated file extension of any of the preset values from the FilterBuilder.Filters enum (in this case ".txt").

Example #2 -- Many common music files filter:

'Declarations
Dim FilterBuild As New FilterBuilder()
Dim ofd As New OpenFileDialog()

'Make an array of filters
Dim filters() As FilterBuilder.Filters = { _
FilterBuilder.Filters.MP3_AudioFiles, _
FilterBuilder.Filters.AAC_Files, _
FilterBuilder.Filters.WAVE_AudioFiles, _
FilterBuilder.Filters.MPEG2_AudioFiles, _
FilterBuilder.Filters.RealAudioFiles, _
FilterBuilder.Filters.MIDI_Files}

'Add the "filters" array - the add method is overloaded
FilterBuild.Add(filters)

With ofd

	'Set the filter
	.Filter = FilterBuild.ToString()

 	'Sets the selected item in the filter box to MP3 files
 	.FilterIndex = FilterBuild.GetFilterIndex( _
 	FilterBuilder.Filters.MP3_AudioFiles)

	'Set the default extension
	.DefaultExt = ".mp3"

	.ShowDialog()

End With

You can use the GetFilterIndex method (as shown above) to get a relevant FilterIndex that you can assign to the FilterIndex property of the OpenFileDialog/SaveFileDialog.

Example #3 -- Custom & system filters:

'Declarations
Dim FilterBuild As New FilterBuilder()
Dim ofd As New OpenFileDialog()

'Add the Custom filters
FilterBuild.Add("Foo Files", "foo")
FilterBuild.Add("Custom Files", "custm")
FilterBuild.Add("My Random Files", "rndm")

'System File Types
FilterBuild.Add("xml")
FilterBuild.Add("dll")
FilterBuild.Add("bat")

With ofd

        'Set the filter
        .Filter = FilterBuild.ToString()

        'Sets the filter index to the first item
        .FilterIndex = 1

        'Set the default extension
        .DefaultExt = ".foo"

        .ShowDialog()

End With

In this last example above, I am adding six file types, with the first three being custom (made up by the programmer), and the last three being known file types obtained from the registry. See the "Custom Filters" and "System File Types" sections above in this article for more information.

Points of Interest

I encountered something particularly weird when writing the overloaded Add methods. Initially, I had written two of the Add methods to take a ParamArray of values from the FilterBuilder.Filters enum for convenience, but when I was testing the Add methods in the IDE, I found that Intellisense did not appear for the enum values after typing ".Add(". Maybe Intellisense doesn't show with ParamArrays?

I overcame this problem by modifying the two Add methods to accept Arrays (instead of ParamArrays) of type FilterBuilder.Filters. See the "Examples" section above.

Credits

Thanks to Man Vuong and his article Get Registered File Types and Their Associated Icons in C# [^]. I have modified some of his source code and converted it to VB.NET to provide System File Types support.

History

25 October 2009 - Version 1.25

  • Added a "WindowsIcons" and a "EXIF_ImageFiles" filter to the FilterBuilder.Filters enum
  • Added a GetFileDescription() method
  • Added a ReadOnly Count() property
  • Added new overloads of the GetFileDescription(), GetFileExtension() and GetFilterIndex() methods that accept a filter string as the only parameter

    For System File Types Support:

  • Added a GetSystemFileTypeDescription() method
  • Added a GetSystemFileTypeIcon() method
  • Added a GetSystemFileTypeInfo() method
  • Added a GetSystemFileTypes() method
  • Modified the FilterGroup class to include support for the new System File Types (see "System File Types" section above)
  • Added a new overload of the "Add" method in both the FilterBuilder and FilterGroup classes, that accepts just one string parameter (the extension) and fetches the file description from the user's computer
  • Added a new overload of the "Contains" and "Remove" methods in the FilterBuilder class to support the new System File Types
  • Added a FileTypeIconSize() property
  • Added an ImageSize enum
  • Modified Example #3 in this article to include a System File Types example
  • Added an Example #7 in the attached demo download. This example demonstrates the methods used when interacting with System File Types.
  • Changed the demo download User Interface to include interactive examples of System File Types. Download the new demo now and see the changes!

06 September 2009 - Version 1.10

  • Added an "All Files" filter to the FilterBuilder.Filters enum
  • Changed the string overload of the Add method. It originally accepted one string parameter (the custom filter string), but thanks to a suggestion from Kschuler it now accepts two string parameters, the description and extension of the file type. See the "Custom Filters" section above in the article.
  • Added a FilterGroup class and modified source code to accommodate the new FilterGroups. See the "FilterGroups" section above in the article.
  • Removed the "obj" folders from the download files. Thanks to pimb2 for this tip.

September 2009 - Version 1.00

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here