Out of the box, Silverlight 4 in-browser applications can’t access files on the user’s hard disk. Although Silverlight contains the System.IO namespace and classes such as File and Directory, we can’t write code that reads a file residing on the disk.
Only if the user specifically allows Silverlight to access a file, the application gets read-only access to the file. The user can allow an application to access a file through the use of the OpenFileDialog. This class is in Silverlight very similar to its WPF/Windows Forms counterpart. We can specify if the user can select a single file, specify the allowed file types etc. Let’s take a look at using the class.
The code for this tip can be downloaded here.
Reading a file using the OpenFileDialog
Assume we want to read a text file, currently located on the desktop. By default, Silverlight can’t read this file so we need the user’s input to allow accessing the file. The location of the file is in fact irrelevant. To open the file in Silverlight, we need the OpenFileDialog. The screenshot below shows the UI of the demo. When clicking on the button, the dialog appears. Note that we direct the user in selecting a text file.
After selecting a text file and clicking OK, the dialog is dismissed, it returns true to the calling application and the Silverlight app gets read-only access to the file. The content of the selected text file is shown in the TextBox control.
Let’s now look at the code for this. In the code below, an OpenFileDialog instance gets created in the constructor. In the click event handler, we specify that a default filter of only text files has to be enforced on the dialog. The MultiSelect is set to false, making only single selections possible.
To actually show the dialog, we use the ShowDialog() method. This method returns a nullable Boolean value, indicating the user selection. If a selection was made, the dialog returns true. When the user clicks OK, the dialog returns true. If the user cancels out of the dialog, false is returned.
private OpenFileDialog _openFileDialog;
public MainPage()
{
InitializeComponent();
_openFileDialog = new OpenFileDialog();
}
private void OpenFileButton_Click(object sender, RoutedEventArgs e)
{
_openFileDialog.Filter = "Text Files (.txt)|*.txt|All Files (*.*)|*.*";
_openFileDialog.Multiselect = false;
bool? dialogResult = _openFileDialog.ShowDialog();
if (dialogResult.Value)
{
Stream fileStream = _openFileDialog.File.OpenRead();
using (StreamReader reader = new StreamReader(fileStream))
{
FileTextBox.Text = reader.ReadToEnd();
}
fileStream.Close();
}
}
Since we allowed only a single selection here, we get access to the file using the File.OpenRead(). The File property is of type FileInfo. Normally, a FileInfo also contains information about the location of the file. However, this information is not available to the Silverlight application. We get a SecurityException if we try to access this file.
Using this code, the file is opened for reading and a Stream to the file is now established. With just regular System.IO code, we can read out the content of the file.
Allowing more than one file
In most cases, allowing just a single file selection is enough. However, in some cases, we may want the user to be able to select more files at the same time. By setting the MultiSelect property to true, we allow exactly this. After hitting OK, the dialog now fills its Files property, an IEnumerable of FileInfo instances. We can loop over this list to read out all the files as follows.
private void OpenMultipleFileButton_Click(object sender, RoutedEventArgs e)
{
_openFileDialog.Filter = "Text Files (.txt)|*.txt|All Files (*.*)|*.*";
_openFileDialog.Multiselect = true;
bool? dialogResult = _openFileDialog.ShowDialog();
if (dialogResult.HasValue && dialogResult.Value)
{
FileTextBox.Text = string.Empty;
foreach (var file in _openFileDialog.Files)
{
Stream fileStream = file.OpenRead();
using (StreamReader reader = new StreamReader(fileStream))
{
FileTextBox.Text += reader.ReadToEnd();
}
fileStream.Close();
}
}
}
Using a simple loop, we read out all selected files.
Where can I place my OpenFileDialog code?
Since opening a file has security implications, you can’t just place this code anywhere you want. User interaction with the application is required before the OpenFileDialog can be called. This essentially means that we can use it from a Button click event, but not in the constructor of a UserControl. If we try the latter, the following will happen:
As the error states, Dialogs must be user-initiated.
It’s also advised against using the OpenFileDialog in full-screen applications. If you would do so, the application will exit full screen mode anyhow.
Summary
In this tip, we saw how to use the OpenFileDialog. We saw how to read a file, read multiple files and where to place the code to work with the class.
About Gill
Gill Cleeren is Microsoft Regional Director (www.theregion.com), Silverlight MVP (former ASP.NET MVP), INETA speaker bureau member and Silverlight Insider. He lives in Belgium where he works as .NET architect at Ordina. Passionate about .NET, he’s always playing with the newest bits. In his role as Regional Director, Gill has given many sessions, webcasts and trainings on new as well as existing technologies, such as Silverlight, ASP.NET and WPF at conferences including TechEd Berlin 2010, TechDays Belgium, DevDays NL, NDC Oslo Norway, SQL Server Saturday Switserland, Spring Conference UK, Silverlight Roadshow in Sweden… He’s also the author of many articles in various developer magazines and for SilverlightShow.net. He organizes the yearly Community Day event in Belgium.
He also leads Visug (www.visug.be), the largest .NET user group in Belgium. Gill recently published his first book: “Silverlight 4 Data and Services Cookbook” (Packt Publishing). You can find his blog at www.snowball.be.
Twitter: @gillcleeren