by kirupa |
7 August 2007
In the previous page, we wrapped up opening multiple files using our Open
File dialog window. Let's wrap up this tutorial by discussing an issue that
exists with WPF in Vista when displaying the Open File dialog.
If you take a close look at the OpenFileDialog under Windows Vista, you'll find
that it looks out of place with its old-school style and low quality icons:
[ the old-school Open File dialog window ]
This is actually not a feature. To display the proper OpenFileDialog in Windows Vista and earlier versions,
one solution is to call the WinForms version of OpenFileDialog. To do that, first
you will need to add a reference to System.Windows.Forms. From your Solution
Explorer in Visual Studio / C# Express, right click on the References folder and
select Add Reference:
[ we need to add a reference to your project ]
After you have selected the Add Reference menu item, the Add Reference window
will appear. From this window, make sure the .NET tab is selected. Scroll down
until you find the System.Windows.Forms Component Name:
[ let's add the System.Windows.Forms namespace ]
Select System.Windows.Forms and press OK to add the reference to this
component and to close the Add Reference window.
Now that your reference has been added, we need to add a new
using statement to get our C# file to use
components stored in System.Windows.Forms. In your Window1.xaml.cs file (which
should be open anyway), add the System.Windows.Forms namespace to your list of
using statements:
- using
System;
- using
System.IO;
- using
System.Net;
- using
System.Windows;
- using
System.Windows.Controls;
- using
System.Windows.Data;
- using
System.Windows.Media;
- using
System.Windows.Media.Animation;
- using
System.Windows.Navigation;
- using
Microsoft.Win32;
- using
System.Windows.Forms;
After you have added your new using statement, press F6 to build your
application. You will notice that you now receive a few errors:
[ two errors now appear because of an incompatibility ]
The errors are caused because the OpenFileDialog class exists in both your
Microsoft.Win32 namespace as well as you newly added System.Windows.Forms
namespace. To resolve this problem, right click on each instance of the
OpenFileDialog class in your code, select Resolve, and from the next menu,
select System.Windows.Forms.OpenFileDialog:
[ select your OpenFileDialog window ]
You'll need to repeat the above process for each OpenFileDialog instance that
exists in your code. For example, this is how my code now looks like:
- private
void
WindowLauncher(object
sender,
RoutedEventArgs
e)
- {
-
System.Windows.Forms.OpenFileDialog
ofd
=
new
System.Windows.Forms.OpenFileDialog();
- ofd.Multiselect
=
true;
-
- ofd.Filter
=
"Data Sources (*.txt, *.xml)|*.txt*;*.xml|All
Files|*.*";
-
- if
(ofd.ShowDialog()
==
true)
- {
- string[]
filePath
=
ofd.FileNames;
- string[]
safeFilePath
=
ofd.SafeFileNames;
- }
- }
Notice that OpenFileDialog object declaration and initialization explicitly
maps out the path through System.Windows.Forms to avoid the ambiguity that
exists with the similar OpenFileDialog that exists in Microsoft.Win32.
When you build your application again, you'll run into another error. This
time, our earlier code where we check if our dialog window returns a true for
opening a file no longer works. In the WinForms version of OpenFileDialog,
you'll need to explicitly select your dialog window's OK button as having been
pressed, and you can do that via the WinForms DialogResult enum:
- private
void
WindowLauncher(object
sender,
RoutedEventArgs
e)
- {
- System.Windows.Forms.OpenFileDialog
ofd
=
new System.Windows.Forms.OpenFileDialog();
- ofd.Multiselect
=
true;
-
- ofd.Filter
=
"Data Sources (*.txt, *.xml)|*.txt*;*.xml|All
Files|*.*";
-
-
- if
(ofd.ShowDialog()
==
System.Windows.Forms.DialogResult.OK)
- {
- string[]
filePath
=
ofd.FileNames;
- string[]
safeFilePath
=
ofd.SafeFileNames;
- }
- }
Notice that instead of checking if ShowDialog returns true, I check to see if
it was the OK button that was used to close the dialog window. If you build and
run your application again, you will not receive any errors. If you are running
a non-Vista version of Windows, you'll display the usual Open File dialog
window, but if you are running Vista, you will see the more native Open File
dialog window instead:
[ the correct, proper version of the Open File dialog window ]
A valid question would be to ask why the Win32 version should even be used when
dealing with dialog windows. The main reason is that all dialog windows
including the Windows.Forms versions, internally call the same lower level
implementation of the dialog window. Ideally, it should not matter whether you
create your OpenFileDialog object using the Win32 namespace or the Windows.Forms
namespace. The end result should be that the best version of the dialog window
that can be displayed by your OS should be displayed.
I believe that future versions of WPF will fix this inconsistency, so
hopefully you will not have to create this workaround using Windows.Forms inside
a WPF application in the future. A fix would automatically cause any WPF
applications that use the currently-incorrect Win32 calls to
automatically display the new version. If you are willing to risk the wait, you
can use the default Win32 approach and automatically display the new windows
when the fix is made. If you want to provide a good UI now,
you can make the call to the dialog window using Windows.Forms as described in
this page.
For a more detailed look at why the Win32 version of
OpenFileDialog still displays the legacy window, check out
my
blog entry on this topic.
Just a final word before we wrap up. If you have a question and/or want to be part of a friendly, collaborative community of over 220k other developers like yourself, post on the forums for a quick response!
|