Jul 15, 2015

The OpenFileDialog

Whenever you open or save a file in almost any Windows application, you will see roughly the same dialogs for doing that. The reason is of course that these dialogs are a part of the Windows API and therefore also accessible to developers on the Windows platform.
For WPF, you will find standard dialogs for both opening and saving files in the Microsoft.Win32 namespace. In this article we'll focus on the OpenFileDialog class, which makes it very easy to display a dialog for opening one or several files. 


<Window x:Class="WpfTutorialSamples.Dialogs.OpenFileDialogSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="OpenFileDialogSample" Height="300" Width="300">
    <DockPanel Margin="10">
        <WrapPanel HorizontalAlignment="Center" DockPanel.Dock="Top" Margin="0,0,0,10">
            <Button Name="btnOpenFile" Click="btnOpenFile_Click">Open file</Button>
        </WrapPanel>
        <TextBox Name="txtEditor" />
    </DockPanel>
</Window>
 
 
using System;
using System.IO;
using System.Windows;
using Microsoft.Win32;
namespace WpfTutorialSamples.Dialogs
{
        public partial class OpenFileDialogSample : Window
        {
                public OpenFileDialogSample()
                {
                        InitializeComponent();
                }

                private void btnOpenFile_Click(object sender, RoutedEventArgs e)
                {
                        OpenFileDialog openFileDialog = new OpenFileDialog();
                        if(openFileDialog.ShowDialog() == true)
                                txtEditor.Text = File.ReadAllText(openFileDialog.FileName);
                }
        }
}
 
  
Once you click the Open file button, the OpenFileDialog will be instantiated and shown. Depending on which version of Windows you're using and the theme selected, it will look something like this: 
 
 
 he ShowDialog() will return a nullable boolean value, meaning that it can be either false, true or null. If the user selects a file and presses "Open", the result is True, and in that case, we try to load the file into the TextBox control. We get the complete path of the selected file by using the FileName property of the OpenFileDialog.

Filter

Normally when you want your user to open a file in your application, you want to limit it to one or a couple of file types. For instance, Word mostly opens Word file (with the extension .doc or .docx) and Notepad mostly open text files (with the extension .txt).
You can specify a filter for your OpenFileDialog to indicate to the user which types of file they should be opening in your application, as well as limiting the files shown for a better overview. This is done with the Filter property, which we can add to the above example, right after initializing the dialog, like this:
openFileDialog.Filter = "Text files (*.txt)|*.txt|All files (*.*)|*.*";
Here's the result: 



Notice how the dialog now has a combo box for selecting the file types, and that the files shown are limited to ones with the extension(s) specified by the selected file type.
The format for specifying the filter might look a bit strange at first sight, but it works by specifying a human-readable version of the desired file extension(s) and then one for the computer to easily parse, separated with a pipe (|) character. If you want more than one file type, as we do in the above example, each set of information are also separated with a pipe character.
So to sum up, the following part means that we want the file type to be named "Text files (*.txt)" (the extension in the parenthesis is a courtesy to the user, so they know which extension(s) are included) and the second part tells the dialog to show files with a .txt extension:
Text files (*.txt)|*.txt
Each file type can of course have multiple extensions. For instance, image files could be specified as both JPEG and PNG files, like this:
openFileDialog.Filter = "Image files (*.png;*.jpeg)|*.png;*.jpeg|All files (*.*)|*.*";
Simply separate each extension with a semicolon in the second part (the one for the computer) - in the first part, you can format it the way you want to, but most developers seem to use the same notation for both parts, as seen in the example above.

Setting the initial directory

The initial directory used by the OpenFileDialog is decided by Windows, but by using the InitialDirectory property, you can override it. You will usually set this value to a user specified directory, the application directory or perhaps just to the directory last used. You can set it to a path in a string format, like this:
openFileDialog.InitialDirectory = @"c:\temp\";
If you want to use one of the special folders on Windows, e.g. the Desktop, My Documents or the Program Files directory, you have to take special care, since these may vary from each version of Windows and also be dependent on which user is logged in. The .NET framework can help you though, just use the Environment class and its members for dealing with special folders:
openFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
In this case, I get the path for the My Documents folder, but have a look at the SpecialFolder enumeration - it contains values for a lot of interesting paths.

Multiple files

If your application supports multiple open files, or you simply want to use the OpenFileDialog to select more than one file at a time, you need to enable the Multiselect property. In the next example, we've done just that, and as a courtesy to you, dear reader, we've also applied all the techniques mentioned above, including filtering and setting the initial directory: 

<Window x:Class="WpfTutorialSamples.Dialogs.OpenFileDialogMultipleFilesSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="OpenFileDialogMultipleFilesSample" Height="300" Width="300">
    <DockPanel Margin="10">
        <WrapPanel HorizontalAlignment="Center" DockPanel.Dock="Top" Margin="0,0,0,10">
            <Button Name="btnOpenFile" Click="btnOpenFiles_Click">Open files</Button>
        </WrapPanel>
        <ListBox Name="lbFiles" />
    </DockPanel>
</Window>
using System;
using System.IO;
using System.Windows;
using Microsoft.Win32;
namespace WpfTutorialSamples.Dialogs
{
        public partial class OpenFileDialogMultipleFilesSample : Window
        {
                public OpenFileDialogMultipleFilesSample()
                {
                        InitializeComponent();
                }

                private void btnOpenFiles_Click(object sender, RoutedEventArgs e)
                {
                        OpenFileDialog openFileDialog = new OpenFileDialog();
                        openFileDialog.Multiselect = true;
                        openFileDialog.Filter = "Text files (*.txt)|*.txt|All files (*.*)|*.*";
                        openFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
                        if(openFileDialog.ShowDialog() == true)
                        {
                                foreach(string filename in openFileDialog.FileNames)
                                        lbFiles.Items.Add(Path.GetFileName(filename));
                        }
                }
        }
}
 
 
If you test this code, you will see that you can now select multiple files in the same directory, by holding down either Ctrl orShift and clicking with the mouse. Once accepted, this example simply adds the filenames to the ListBox control, by looping through the FileNames property.
 

No comments:

Post a Comment