Random geekery since 2005.

Husband, father, programmer, speaker, writer, blogger, podcaster, collector, traveler, golfer.

31 Days of Windows 8 | Day #19: File Picker

Written in

by

This article is Day #19 in a series called 31 Days of Windows 8.  Each of the articles in this series will be published for both HTML5/JS and XAML/C#. You can find additional resources, downloads, and source code on our website.

advertisementsample

Today, we are going to look at another invaluable tool in Windows 8 development, the File Picker.  There are millions of ways to use the File Picker, but when you boil it down, you’re going to need to get files from the user’s computer for something.  This article will show you how to do it.

Updating Your Package.Appxmanifest

As with all of the different mechanisms we’ve used to interact with the user’s system, we need to start with updating our package.appxmanifest file.  Since we are going to be both opening files AND saving files in this article, we need to add both of those Declarations to our file.

For the File Open Picker, you’ll start with a form that looks like this:

19-XAML-FileOpenManifestBroken

You’re expected to make one of two choices:

  • Supports any file type.  By checking this box, you are declaring that you could access any file type from your application.
  • Supported file type.  You can also specify which file types you want to open, so if your app only opens Excel files, for example, you could list “.xls” as your file type.

For this demo, you can just select “Supports any file type.”  The same process can be done for the File Save Picker, which offers you the same choices, like this:

19-XAML-FileSaveManifestBroken

Getting a File from Your User’s Machine

This article is going to build a progressively more complex app for selecting files from a user’s machine.  We’ll start getting just one file, then multiple files, and then multiple files of only a specific file type (.png).  Most of the code for each example is identical, so we’ll focus on what is the “new” code in each step.

For selecting a single file from the user’s hard drive, we are going to start with the FileOpenPicker object.  This is the object that will open the File Picker dialog for the user, help them select one or many files, and return them to us.  It has many options, and we’ll work our way through all of them.  For selecting a single file, of any type, the code starts quite simply:

FileOpenPicker picker = new FileOpenPicker();
picker.FileTypeFilter.Add(".xls");
StorageFile file = await picker.PickSingleFileAsync();

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

You’ll notice that we have to set a FileTypeFilter when we create a FileOpenPicker.  You are not allowed to provide a wildcard, or just ignore the filter.  You have to provide at least one, but you can also provide several, which means you can list 8-10 common file types (especially when you’re looking for images on the user’s device, because they could be PNG, JPG, JPEG, GIF, BMP, etc.) When you run this, your user will see an interface that looks like this:

19-XAML-FilePicker

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

This is the File Picker interface, and once the user selects a file, it will be returned to your application as a StorageFile, which we have worked with in several of the previous articles in this series.

Next, we might have a good idea as to where the user should start looking for the files they would want to open in your app.  Maybe it’s their Photos collection, or Music.  We can specify one of 8 locations on their computer:

19-XAML-PickerLocationId

So, to get the File Picker to open in one of these locations, you need to add one line of code to your method, so that it looks like this (you can see I’ve added a few new filters as well):

FileOpenPicker picker = new FileOpenPicker();
picker.FileTypeFilter.Add(".png");
picker.FileTypeFilter.Add(".jpg");
picker.FileTypeFilter.Add(".gif");
picker.FileTypeFilter.Add(".bmp");
picker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
StorageFile file = await picker.PickSingleFileAsync();
 

This time the File Picker will launch directly to the location you’ve specified (in my example, it is the Pictures Library):

19-XAML-FilePicker-Location

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

The last option we can manipulate relates to how the File Picker will display the files.  Simply use the ViewMode property of the FileOpenPicker object, like this:

picker.ViewMode = PickerViewMode.List;
 

Your options are limited to List or Thumbnail, but they look distinctly different.  Thumbnail ONLY shows a square image representing the file.  List shows an icon as well, but also shows some of the metadata for the files.  Here’s a look at the same folder with each view (click to enlarge):

List

19-XAML-List

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Thumbnail

19-XAML-Thumbnail

Retrieving Multiple Files From Your User’s Computer

Sometimes, we want to grab more than one file at a time.  In this case, we can use a different method call on our FileOpenPicker object.  This time, we’ll use the PickMultipleFilesAsync() method.

FileOpenPicker picker = new FileOpenPicker();
picker.FileTypeFilter.Add(".png");
picker.FileTypeFilter.Add(".jpg");
picker.FileTypeFilter.Add(".bmp");
picker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
picker.ViewMode = PickerViewMode.Thumbnail;
IReadOnlyList<StorageFile> files = await picker.PickMultipleFilesAsync();
 

So, more or less, there’s very little difference between selecting one or multiple files from a code perspective.  We do receive a collection of StorageFile objects rather than just one, but that should be expected when we’re enabling multiple files to be selected.

What is different, at least from what I can tell, is HOW the user can select multiple files.

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

19-XAML-MultipleFileSelection

As you can see from the image above (click to enlarge), not only can we select multiple files, but we can also see that there is a “basket” of sorts at the bottom of the File Picker interface.  This shows a list of the files that the user has selected.  What it also enables, however, is a way for a user to select multiple files at once, from completely different folders.  Your users will be able to select a few files from one folder, and a few files from another, and they’ll all be provided to your application at once, without your user having to make multiple trips to those folders.  This is an absolutely awesome feature that should not be overlooked.

In our final section of this article, let’s look at how we can use the File Picker to also save files to a user’s machine.

Saving a File To Your User’s Hard Drive

One of the related operations we may want to use is to save a file to your user’s machine.  This is different from what we talked about on Day #8 of this series, where we were saving files internal to our application.  In this instance, we are saving a permanent file that will continue to live on the user’s machine, even if our app is uninstalled.  If your files are unusable by other apps, this is likely NOT the way you’d want to store your files.  I generally recommend saving files like this for file types that could be opened by a variety of applications.  To do this, it looks very similar to our FileOpenPicker, but it’s now a FileSavePicker.

The other diffference with this situation is that we are writing data to the user’s hard drive.  This means we have all of the other hassles that come with it.  Files can be open already, they can be edited by other apps, or even deleted as we’re working with them.  So we will first launch the File Save Picker to determine where the user wants to save their file (as well as what file type and name they want to give it.  This looks like this:

19-XAML-FileSave

And here’s what the code looks like to make this entire process happen:

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

FileSavePicker saver = new FileSavePicker();
saver.SuggestedStartLocation = PickerLocationId.Desktop;
saver.FileTypeChoices.Add("Text File", new List<string>() { ".txt" });
saver.FileTypeChoices.Add("Microsoft Excel", new List<string>() { ".xls" });
saver.FileTypeChoices.Add("Image", new List<string>() { ".png", ".jpg", ".bmp" });
saver.SuggestedFileName = "PeriodicTableOfTheElements";
StorageFile file = await saver.PickSaveFileAsync();
 
if (file != null)
{
    CachedFileManager.DeferUpdates(file);
    await FileIO.WriteTextAsync(file, "This is a link to the Periodic Table of the Elements.  http://www.ptable.com/  You didn't expect to find all of the contents here, did you?");
    FileUpdateStatus status = await CachedFileManager.CompleteUpdatesAsync(file);
}
 

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

In this case, you can see that the beginning of our code sample doesn’t look that different.  Instead of filters, we can add FileTypeChoices which function as the different formats our user might want to save their file.  The choices I’ve included don’t really make much sense together, but it helps to illustrate that you can specify any file types (or types) in this list.  It’s at your full control.

In addition, once the user has selected a location and name for their file, we’re not done.  If they actually returned those values to use, our next step is to actually write the file to the drive itself.  Inside our if statement, we use the DeferUpdates() method to prevent any additional edits to the file that we’re working with.  They will be “deferred” until after our operation is complete.  Next, we write the contents of our file.  Finally, we commit those changes using the CompleteUpdatesAsync() method.  This is where all of the work is actually completed.

You’ll find that if the file already exists, you’ll also get prompted with a “Replace the existing file?” dialog box.

19-XAML-ReplaceDialog

Ultimately, that’s all it takes to save a simple file to the user’s system.  For more complex operations and file types, you’re going to want to explore the FileIO class.  You can read more about that on MSDN.

Selecting a Folder on the User’s Machine

The last topic I want to cover in this article is also very related to the others: selecting a folder from the user’s machine instead of a specific file.  This is great for allowing the user to choose a default save location for the future, or perhaps a place for you to look for files in the future.  What’s great about this process is that once the user has selected a folder, we can save it as our default folder, and we are granted explicit rights to read and write to/from this folder in the future without having to request future access.  Here’s how we do it.

FolderPicker picker = new FolderPicker();
picker.FileTypeFilter.Add(".xls");
StorageFolder folder = await picker.PickSingleFolderAsync();
if (folder != null)
{
    StorageApplicationPermissions.FutureAccessList.AddOrReplace("DefaultFolder", folder);
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

As you can see, our first three lines of code look very familiar.  However, if we confirm that an actual folder was returned to us, we can save this to the StorageApplicationPermissions.FutureAccessList as a place we have been granted permission to use.  Saving it this way, and referring to it in the future will limit the number of times you have to ask your user for permission to save a file to their system.

Summary

Today, we looked at several different ways to help our users interact with the files that live on their machine.  We saw how to open single and multiple files, save files back to the hard drive, and even select default save locations for future use.  You’ll likely find yourself using these methods over and over in your apps, so this is an important lesson to learn.

If you would like to download the sample code that was discussed in this article, click the icon below:

downloadXAML

Tomorrow, we’re going to take a look at another common feature you’re likely to run into: Printing.  We’ll look at how to communicate with a user’s printers, as well as how we register with the system to make printing even easier.  See you then!

downloadTheTools

Tags

One response to “31 Days of Windows 8 | Day #19: File Picker”

  1. vishnu.gb Avatar
    vishnu.gb

    Can you tell me how to give the picker location id so that i get access to a particular folder in the local drive instead of giving picturelibrary or videolibrary

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Create a website or blog at WordPress.com

%d bloggers like this: