Different ways to keep state when building RIA with Silverlight

When building RIA with Silverlight, we will have some state issues we need to take care of. A Silverlight app by default is running in a browser, the browser have 3 bad buttons, Refresh, back and forward. If a user will press the Refresh button, the whole Silverlight app will be restarted. Same if they navigate from a Silverlight app with the back and forward buttons. If we build a RIA, our app will mostly hold the state for us on the client-side to reduce the number of round trip to the server etc. Lets assume a user will work with customer data. A user want to update the customer and information related to the customer. After 10 minutes of changes, the user suddenly by mistake refresh the page and all the data will be lost. So what we need to do when building RIA, is to remember the Refresh, back and forward buttons. This blog post will cover some of the Silverlight 3.0 features we can use to hold state and handle the Refresh, back and forward issues. This is something that I will also take up in my new updated Silverlight 3.0 course at Cornerstone (Where I work as an instructor, mentor, coach and consultant).

What features can we used in a RIA to keep states and handle the the three evil buttons?

We can for example use the following features:

IsolatedStorage

OpenFile- and SaveFileDialog classes

DataContext and NavigationCache

Cookies

The IsolatedStorage is a great “tool” to save data to the client-side to keep states. IsolatedStorage is also a nice solution to save data when working offline, for example when using the Out-of browser in Silverlight 3.0. By saving data to the IsolatedStorage while a user works with the data, can prevent them to lose data if they use the refresh, back and forward buttons. If a user will close the application, or restart the computer, the data will still exists. There are of course something we need to have in mind when using the IsolatedStorage, for example Administrators can set a limit of how much data a user can store on the disk, so we can’t be sure if we can save the data we need to save. So in this case we need to add exception handling and use another solution to keep the state. If we need to store a lot of data, we may need to request more space on the client’s disk. So a good practice is to request for the amount of data needed. The following is an example of using the IsolatedStorage:

using (IsolatedStorageFile isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream isolatedStorageFileStream = isolatedStorageFile.CreateFile("mydata.txt"))
{
using (StreamWriter sw = new StreamWriter(isolatedStorageFileStream ))
{
sw.Write("This is the data I want to store);
sw.Close();
}
}
}

When using the IsolatedStorage we can both work with files and dictionaries, the IsolatedSotrage is like a virtual disc.

When working with out-of browser and an offline mode, we can also use the OpenFile- and SaveFileDialog. By using those features, we can make sure the user gets a request to save the data when the user leaves the Silverlight Application. The user can also Open a file to continue working with previous data. The following is an example of using the SaveFileDialog added to Silverlight 3.0:

var sfd = new SaveFileDialog()
{
DefaultExt = "txt",
Filter = "Text files (*.txt)|*.txt|All files (*.*)|*.*",
FilterIndex = 1
};

if (sfd.ShowDialog() == true)
{
using (Stream stream = sfd.OpenFile())
{
//Write data to the stream
stream.Close();
}
}

When using the IsolatedStorage, we can read, write, remove and create dictionaries etc without a permission from the user, but when saving to the user’s disc, we need to ask the user to decide if he/she wants to save the data, and also load data by using the OpenFileDialog class.

Something that will not solve the Refresh button problem, but can be used to keep state when using the Back and Forward button while using the Navigation feature in Silverlight 3.0, is to use the DataContext on a an UI element on the MainPage. The DataContext on an “UI Element” will share it’s data to all of the “UI element’s” children. When using the Frame in Silverlight 3.0 to handle navigation between pages, the pages we navigate to will always be created. So if we navigate from page 1 to page 2, page 1 will be destroyed, and page 2 created. If we press the back button, Page 2 will be destroyed and Page 1 will be created. The page that has the Frame, will no be recreated. So states can be kept on the MainPage. By using the DataContext on a “UI element” on the MainPage, we can decide what data to keep in memory. If we want to save a whole page into the memory we can use the NavigationCache feature.

By turning the NavigationCache (by setting the NavigationCacheMode to Enabled on a page) on, we will make sure the Page will be added to a cache, so it will not be recreated when we navigate to it, it will not be destroyed when navigation from it. The NavigationCache should not be used to save information unique to each users. Make sure to enable it only if you new that you frequently need to access a page, and want to increase performance by not recreating the page all the time a user navigates to it. The NavigationCache also have a CacheSize, so if you exceed the size, some pages in the cache will be disposed. So by setting the NavigationCacheMode to Required, will skip the use of the CacheSize and always cache the page.

 

Cookies can also be used to save state, but cookies have a limitation of size, and can also be turned of by the user. If you need to only save small piece of data, cookie could be used to keep the state.

There are several solutions that can be used to handle the Refresh, Back and Forwad button issues when building RIA. In this blog post I mentioned some features that can be used. The important thing is to have the button problem in mind when building RIA. The solution you use to keep that state, will be based on what data and how much data you need to save. I hope this blog post gave you some tips.

No Comments