C H A P T E R 8
■ ■ ■
183
Local Storage in Silverlight
Localized storage in Silverlight is handled by its isolated storage feature, which is a virtual file system
that can be used to store application data on the client’s machine. As just a few examples, you might use
local storage in your application to store user settings, undo information, shopping cart contents, or a
local cache for your commonly used objects. Implementations of this feature are really limited only by
your imagination.
In this chapter, you will explore Silverlight’s isolated storage. I will walk you through building a
virtual storage explorer to view the directories and files contained within isolated storage for an
application. In addition, you will look at the isol ated storage quota and how to increase the quota size
for your Silverlight applications.
Working with Isolated Storage
Storing application information has always been a challenge for developers of traditional web
applications. Often, implementing such storage means storing information in cookies or on the
server, which requires using a postback to retrieve the data. In the case of desktop applications,
implementing storage for application information is significantly easier, as developers have more
access to the user’s hard drive. Once again, Silverlight bridges the gap between desktop applications
and web applications by offering isolated storage.
Using the Silverlight classes for working with isolated storage, you can not only store settings
locally, but also create files and directories, as well as read and write files within isolated storage.
Using the Isolated Storage API
The classes for accessing isolated storage are contained within the System.IO.IsolatedStorage
namespace. This namespace contains the following three classes:
• IsolatedStorageFile
• IsolatedStorageFileStream
• IsolatedStorageSettings
You’ll look at each class to see what it represents.
CHAPTER 8 ■ LOCAL STORAGE IN SILVERLIGHT
184
IsolatedStorageFile
The IsolatedStorageFile class represents the isolated storage area, and the files and directories
contained within it. This class provides the majority of the properties and methods used when working
with isolated storage in Silverlight. As an example, in order to get an instance of the user’s isolated
storage for a given application, use the static method GetUserStoreForApplication(), as fol lows:
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
{
//...
}
Once the storage instance has been retrieved, a number of operations are available, including
CreateDirectory(), CreateFile(), GetDirectoryNames(), and GetFileNames(). Also, the class has
properties, such as Quota and AvailableFreeSpace. The following example creates a directory in
isolated storage called Directory1, and then it retrieves the total and available free space in isolated
storage:
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
{
store.CreateDirectory("Directory1");
long quota = store.Quota;
long availableSpace = store.AvailableFreeSpace;
}
IsolatedStorageFileStream
The IsolatedStorageFileStream class represents a given file. It is used to read, write, and create files
within isolated storage. The class extends the FileStream class, and in most cases, developers will use a
StreamReader and StreamWriter to work with the stream. As an example, the following code creates a
new file named TextFile.txt and writes a string to the file:
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
{
IsolatedStorageFileStream stream = store.CreateFile("TextFile.txt");
StreamWriter sw = new StreamWriter(stream);
sw.Write("Contents of the File);
sw.Close();
}
IsolatedStorageSettings
The IsolatedStorageSettings class allows developers to store key/value pairs in isolated storage. The
key/value pairs are user-specific and provide a very convenient way to store settings locally. The
following example demonstrates storing the user’s name in IsolatedStorageSettings.
public partial class MainPage : UserControl
{
private IsolatedStorageSettings isSettings =
IsolatedStorageSettings.ApplicationSettings;
CHAPTER 8 ■ LOCAL STORAGE IN SILVERLIGHT
185
public MainPage()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(Page_Loaded);
this.cmdSave.Click += new RoutedEventHandler(cmdSave_Click);
}
void cmdSave_Click(object sender, RoutedEventArgs e)
{
isSettings["name"] = this.txtName.Text;
SetWelcomeMessage();
}
void Page_Loaded(object sender, RoutedEventArgs e)
{
SetWelcomeMessage();
}
private void SetWelcomeMessage()
{
if (isSettings.Contains("name"))
{
string name = (string)isSettings["name"];
this.txtWelcome.Text = "Welcome " + name;
}
else
{
txtWelcome.Text =
"Welcome! Enter Your Name and Press Save.";
}
}
}
The first time users access the application, they will see the message “Welcome! Enter Your Name
and Press Save.” They can then enter their name and click the Save Name button. The name will be
saved in local storage under the key/value pair called name. The next time the user accesses the
application, his name will still be stored in local storage, and he will see the friendly welcome
message, as shown in Figure 8-1.
CHAPTER 8 ■ LOCAL STORAGE IN SILVERLIGHT
186
Figure 8-1. Saving a user’s name with IsolatedStorageSettings
Now that you have briefly looked at some of the key classes associated with Silverlight’s isolated
storage, let’s try building an application that uses this storage.
Try It Out: Creating a File Explorer for Isolated Storage
In this example, you will create a file explorer that will allow a user to navigate through an
application’s virtual storage within Silverlight’s isolated storage. The file explorer will allow users to
view, modify, and create new files within the given directories. Keep in mind that a Silverlight
application has its own isolated storage, so the file explorer will be unique to the application. The end
result will appear as shown in Figure 8-2.
CHAPTER 8 ■ LOCAL STORAGE IN SILVERLIGHT
187
Figure 8-2. The isolated storage file explorer demo
Creating the Application Layout
Let’s get started by setting up the application layout.
1. Create a new Silverlight application in Visual Studio 2008. Name it
Ch8_ISExplorer and allow Visual Studio to create an ASP.NET web application
called Ch8_ISExplorer.Web to host your application.
2. When the project is created, you should be looking at the MainPage.xaml file. If
you do not see the XAML source, switch to that view so that you can edit the
XAML. The application should take up the entire browser window, so begin by
removing the Width and Height properties from your base UserControl.
<UserControl x:Class="Ch8_ISExplorer.MainPage"
xmlns="
xmlns:x="
<Grid x:Name="LayoutRoot" Background="White">
</Grid>
</UserControl>
CHAPTER 8 ■ LOCAL STORAGE IN SILVERLIGHT
188
3. Next, define a Grid for the form layout. Add two columns and three rows to the
Grid. Set the Width property of the first column to 250. Set the Height property
of the top row to 75 and the bottom row to 30. Also, in or der to better see your
Grid layout, set the ShowGridLines property to True.
<Grid x:Name="LayoutRoot" Background="White" ShowGridLines="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="250" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="75" />
<RowDefinition />
<RowDefinition Height="30" />
</Grid.RowDefinitions>
</Grid>
4. Run your application. It should look like Figure 8-3.
Figure 8-3. The grid layout of the file explorer application
CHAPTER 8 ■ LOCAL STORAGE IN SILVERLIGHT
189
Next, add a GridSplitter to allow the user to resize the left and right columns.
Set the Grid.RowSpan to 3 and HorizontalAlignment to Right.
<Grid x:Name="LayoutRoot" Background="White" ShowGridLines="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="250" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="75" />
<RowDefinition />
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<basics:GridSplitter
Grid.RowSpan="3"
HorizontalAlignment="Right" />
</Grid>
Now you will start filling the Grid cells with controls. You will add quite a few
control s, using n ested StackPanel components to assist in getting the desired
layout. These controls have been discussed in detail in Chapters 4 and 5, and
you can refer back to those chapters for more information about any of the
control s used he re.
5. In Grid.Row and Grid.Column (0,0), place a StackPanel that contains a couple
cosmetic TextBlock controls that will serve as your application title, as
follows (with some of the existing code omitted for brevity):
<Grid x:Name="LayoutRoot" Background="White" ShowGridLines="True">
...
<basics:GridSplitter ...
<StackPanel
VerticalAlignment="Bottom"
Orientation="Vertical"
Margin="5">
<TextBlock
FontSize="18"
FontWeight="Bold"
Text="Silverlight 2">
</TextBlock>
<TextBlock
FontSize="18"
FontWeight="Bold"
Text="Isolated Storage Demo">
</TextBlock>
</StackPanel>
</Grid>
CHAPTER 8 ■ LOCAL STORAGE IN SILVERLIGHT
190
Referring to Figure 8-2, you will notice that the content is divided into two
sections: one for directories (top) and one for files (bottom). Let’s first take
car e of the section for directories.
6. In Grid.Row and Grid.Column (1,0), place another StackPanel, which spans
two rows, with a couple TextBlock controls, three Button control s, and two
ListBox controls. The XAML should appear as follows (again, with some of the
source code omitted, but the changes are shown):
<Grid x:Name="LayoutRoot" Background="White" ShowGridLines="True">
...
<basics:GridSplitter ...
<StackPanel
VerticalAlignment="Bottom"
Orientation="Vertical"
Margin="5">
<TextBlock
FontSize="18"
FontWeight="Bold"
Text="Silverlight 2">
</TextBlock>
<TextBlock
FontSize="18"
FontWeight="Bold"
Text="Isolated Storage Demo">
</TextBlock>
</StackPanel>
<StackPanel
Grid.Row="1"
Grid.RowSpan="2"
Orientation="Vertical">
<TextBlock
FontSize="15"
Text="Directories"
Margin="5">
</TextBlock>
<TextBlock
x:Name="lblCurrentDirectory"
FontSize="13"
Text="Selected Directory"
Margin="5">
</TextBlock>
<StackPanel Orientation="Horizontal">
<Button
x:Name="btnUpDir"
CHAPTER 8 ■ LOCAL STORAGE IN SILVERLIGHT
191
Margin="5"
Click="btnUpDir_Click"
Content="Up Directory"
Width="100"
Height="20" />
<Button
x:Name="btnOpenDir"
Margin="5"
Click="btnOpenDir_Click"
Content="Open Directory"
Width="100"
Height="20" />
</StackPanel>
<ListBox Height="150"
x:Name="lstDirectoryListing"
Margin="5,5,13,5">
</ListBox>
</StackPanel>
</Grid>
First is a simple cosmetic TextBlock for the section title. This is followed by
the TextBlock named lblCurrentDirectory, which will be filled with the
current directory. As the users navigate through the directories, it will be
important to inform them which directory they are in.
Next are two Button controls (btnUpDir and btnOpenDir), which will be used for
navigating through the directories. This is simplified into two basic tasks:
moving up a directory and opening the currently selected directory. To get
the buttons to appear visually as desired, they are contained in a StackPanel
with horizontal orientation.
The final ListBox will be populated with directories named
lstDirectoryListing. As the users navigate through the directories using the
btnUpDir and btnOpenDir buttons, this ListBox will be repopulated
automatically with the directories contained in the user’s current location.
7. Next, still within Grid.Row and Grid.Column (1,0), add the files section , as
follows:
<Grid x:Name="LayoutRoot" Background="White" ShowGridLines="True">
...
<ListBox Height="100"
x:Name="lstDirectoryListing"
Margin="5,5,13,5">
</ListBox>
<TextBlock
FontSize="15"
Text="Files"
Margin="5">
</TextBlock>
CHAPTER 8 ■ LOCAL STORAGE IN SILVERLIGHT
192
<StackPanel Orientation="Horizontal">
<Button
x:Name="btnOpenFile"
Margin="5"
Click="btnOpenFile_Click"
Content="Show File"
Width="100"
Height="20" />
</StackPanel>
<ListBox Height="150"
x:Name="lstFileListing"
Margin="5,5,13,5">
</ListBox>
</StackPanel>
</Grid>
As with the previous section, the first TextBlock holds the section title. Next is
a Button control called btnOpenFile. Notice that even though there is only one
button, it is still placed within a StackPanel for consistency. In the future, if
you want to extend this application—for example, to add file deletion
functionality—you may want to add buttons to this StackPanel. This is purely
user preference; the StackPanel really was not required in this instance.
Finally, you have the ListBox that will be filled with the files in the current
directory, in the same way that the directories ListBox will be filled in the top
section.
8. To see what you have so far, press F5 (or choose Debug Start Debugging
from the menu bar) to start your Silverlight application.
Notice that Visual Studio will compile successfully and will open the browser
instance. However, just when you think everything is going great and you
are excited to see your beautiful form coming to life, you get an
XamlParseException with a cryptic message:
AG_E_PARSER_BAD_PROPERTY_VALUE [Line: 66 Position: 34].
This is caused by the fact that, within the code behind, you have not declared
the delegates that are referred to in your XAML.
■ Note The line and position noted in the error message you see may be slightly different from those shown here,
depending on the spacing you included when adding the controls to the code.
9. Stop debugging by clicking the Stop button. Press F7 or select View View
Code. Sure enough, there are no event handlers.
CHAPTER 8 ■ LOCAL STORAGE IN SILVERLIGHT
193
At this point, you could go through and manually add the handlers in the code.
But I think you’ve done enough typing already, so let’s have Visual Studio do
it for you.
10. Return to your XAML by clicking the MainPage.xaml file in the Files tab. Look
at the controls you have added. You will notice that the code refers to three
event handlers, one for each of the buttons: btnUpDir_Click,
btnOpenDir_Click, and btnOpenFile_Click.
11. Find the first reference, btnUpDir_Click. Right-cl ick it and select the Navigate
to Event Handler option, as shown in Figure 8-4. Visual Studio will
automatically create the event handler in the code behind, as follows:
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
private void btnUpDir_Click(object sender, RoutedEventArgs e)
{
}
}
Figure 8-4. Choosing the Navigate to Event Handler option in Visual Studio
12. Repeat step 11 for the other two event handlers. At this point, your code
behind should look as follows:
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
private void btnUpDir_Click(object sender, RoutedEventArgs e)
{
CHAPTER 8 ■ LOCAL STORAGE IN SILVERLIGHT
194
}
private void btnOpenDir_Click(object sender, RoutedEventArgs e)
{
}
private void btnOpenFile_Click(object sender, RoutedEventArgs e)
{
}
}
13. Run the application. Once again, press F5 to start debugging. Barring any
typos, the Silv erlight application should appear as shown in Fi gure 8-5.
Figure 8-5. Application with left portion layout
It’s looking good so far! You are almost finished with the application layout.
Now, let’s move on to the right column and add the final controls.