Have you ever written a configuration dialog where the user had to enter a filename or a path for your application to do something with?
If you have, then you've probably added a button to browse for a file or folder with some rather trivial
Click event handler: instantiate the appropriate
FolderBrowserDialog, set its properties, call
ShowDialog() and if the
DialogResult.OK, then fill the associated
TextBox with the filename or folder in the dialog.
No big deal, you might say.
A standard procedure, not difficult at all, but something you have to do for the configuration dialog to be user-friendly. And when you have several configuration dialogs or several file paths/folders to configure, you'll end up writing the same trivial piece of code over and over again.
So I thought I could simplify this repetitive task a bit and brush up my knowledge of extender providers...
The File/FolderBrowserExtenderProvider component
IExtenderProvider-based approach appeared appropriate: binding two controls together, one acting as a "Browse"-button and the other one to receive the file or folder selected.
I chose the approach to let the extender provider extend the control to receive the selected file/folder and to provide the button to start browsing.
Writing the extender provider
To develop such a component, you'll have to inherit
IExtenderProvider and specify the name of the property you want to provide in a
ProvidePropertyAttribute, like this:
public class FolderBrowserExtenderProvider : Component, IExtenderProvider
That way, I've specified that my extender provider will add an additional property named "
BrowseButton" to some components and that this property is a
The next step is to say which components can be extended by the new extender provider.
That's done by implementing
CanExtend(). Given an extendee object (i.e., an object that is to be extended), your extender provider must tell whether it can provide the given property for this object.
At first, I returned
true if the extendee derived from
TextBoxBase (that's what you usually have: you enter a filename/folder into a
TextBox), but after a while, I thought I don't have to restrict the developer to this type. Any control has a
Text property that can receive the selected file/folder name, so now this function returns
Next, you'll have to handle setting and retrieving the new property.
The extender provider doesn't really add a new property to an extendee in a way that you could actually write:
myTextBox.BrowseButton = myButton;
Instead, its responsibility is to keep a list of extendees and their assigned properties. Such a list entry is created by calling:
Set<PropertyName>(extendee, property value)
and queried by calling:
In my case, the signatures for these methods look like this:
public Control GetBrowseButton(Control extendee);
public void SetBrowseButton(Control extendee, Control browseButton);
I think most extender providers will use a
HashTable to keep the assignments, that way it's really easy to keep track. My components do just this.
Adding functionality to the extender provider
So far, our extender provider doesn't do anything but remember which control is assigned as a
BrowseButton to which other control. In order to actually start browsing when an assigned
BrowseButton is clicked, we'll have to add a
Click event handler to the
BrowseButton once it's assigned.
Although you'll rarely remove or reassign an extendee, it's a good idea to remove the event handler before the
BrowseButton is reassigned or you'll end up with several dialogs popping up.
Click event handler finally is responsible for showing the appropriate
FolderBrowserDialog. In order to be able to visually design this dialog, each extender provider simply has a public readonly property
One little catch here: in order for the designer to correctly serialize the dialog's properties, I had to set the
DesignerSerializationVisibility.Content, otherwise the reference to the dialog itself is serialized and not the dialog's properties.
Using the extender providers
To use the extender providers in your forms, you should add them to your Toolbox. Then drag them to your Form and each of your controls will show an additional property
None as default value.
Simply select the control you want to click on for the appropriate browse dialog to appear and transfer the selected folder/file to the first control's text.
A basic scenario would be to have a
textBox1) and a
button1) on your
You add a
FolderBrowserExtenderProvider to the
Form and set
BrowseButton property to
button1 and you're done.
You can assign a control to be its own
BrowseButton, by the way. Unfortunately, because of a bug in the code generation of VS, you can't do this visually, or you'll get bogus code. Since there's no workaround or fix up to date, I'm throwing an exception when you try to make such an assignment in the designer.
You can assign the
BrowseButton in code without problems, though.
If you're unsure, just take a look at the sample application included in the source code.
- 05.01.2004 - First release.