Hey guys,

In this post i am going to talk about the most import part of the Silverlight and WPF applications, the View Model and the MVVM pattern.

UI development Challenges

View Models are designed to solve certain problems that pop during the UI designing.

  • The major problem is that the User Interface code is difficult to test especially with automated tests. This is because the Code behind lives in the UI. Suppose we want to test a method in a code behind file like MainPage.xaml.cs then we have no other choice but to make an instance to the MainPage class, so when we do that the constructor is called will call InitializeComponent()  and it will load all the xaml controls which will make the copy of the User Interface tree available and this a major problem in Unit Testing because some components might not work correctly till they are displayed as they make assumptions about the messaging and event handling. So the behavior of MainPage might be different from what it would have been at runtime.
  • Another problem with code behind is that big and complex classes which are really difficult to maintain and are not flexible. You can easily get used to using the code behind for you code because that’s where Visual Studio adds the event handlers automatically. The best approach for coding is to have well defined classes with narrow responsibilities.
  •  The code behind job is to interact with the User Interface objects but when we start to add behaviors in the code behind which interact with User Interface objects we give our classes a wider scope and that’s the start of problems. It becomes all the more problematic when the application logic starts to integrate with the User Interface elements and the state of the application is saved with the help of user Interface elements.
  • Another reason for the problem is overdoing the Data Binding. When you application logic starts depending on your Data Binding states. One example that comes to mind is that when the validation rules are made dependent on Data Binding which should actually always be the part of our application logic.

Separated Presentation

This is the technique which is recommended for overcoming the problems mentioned above. By using separated presentation we can avoid xaml codebehind by removing user interface manipulation logic in code behind, interaction logic in code behind, application logic in code behind and everything else not required in code behind. The best thing to do is to keep as less as code as possible in the xaml code behind. Keep any kind of application logic in a separate class which is generally named as Model. So we should make the model only concerned with the application which says what the application does and not how the user interacts with the application. Now UI class should not have any of the interaction logic because of the problems I described in the previous section so we need to create another class which will hold the interaction logic. This is the View Model. This governs any non-trivial logic. It will have the logic for the User Interface to behave the way we want it to behave.

Model View View Model

So let’s talk about each component.

  • Model – A model is a classic model which comprises of the C# classes. It has not reference to the user interface and is not aware of the existence of any User Interface.  The Model classes are compileable without any reference to the User Interface classes. The types in the Model consist of the concepts our application works with. If should be able to take these classes to any console application, web application or windows application and they should be able to compile with no problems. During the design of the Model we need to take decisions on how will the model be used? For example we situations where the Model is shared by both the client and the server or the model can mostly stay in the server or the model can completely stay in the client.
  • View – View is generally a User Control. In Silverlight it is a good idea to split up the user interface into multiple User Controls.
  • View Model – For each View we write a View Model. So the main purpose of the existence of a View Model is to serve the View. It’s possible for a particular view model to span into multiple classes. The bottom line is that the View model serves the purpose of presenting data or screen to your application. The reason it’s called a view model because adapts a particular model for the specific view. Like the model, the view model is a C# class and is not required to derive from a particular class. Sometimes it makes sense to make a base view model and derive from the same but the pattern does not demand that. But unlike Model it can use Silverlight types in its properties. The important things that define the View Model is that the information flows between View and ViewModel via Data Binding and this enables ViewModel to change the View without having to depend on the view. This is very useful for testability as we can instantiate the ViewModel without having to create the View. We can just use the View Model and invoke the methods and get the values back for testing.

Let’s see some code now.

  • Create a new Silverlight application. And create 3 folders in the Solution Explorer named Model, Views and ViewModel.
Silverlight 4 : Model View View Model

Silverlight 4 : Model View View Model

  • Let’s add a couple of classes in the Models folder. Add 2 new classes named UserModel and MessageModel to the Models folder and add the content as below.

 

Silverlight 4 : Model View View Model

Silverlight 4 : Model View View Model

  • To increase the abstractions lets add a new folder in the solution named services and add an interface to it named IModelProvider and add the following code to it. This abstraction will make testing easier for us.

 

IModelProvider

IModelProvider

 

  • Let’s add another class named ModelProvider.cs in the services folder which will be dummy data provider for this sample application. Add the following code to this class.

 

ModelProvider

ModelProvider

 

ModelProvider

ModelProvider

  • The way we will handle user input in this application is via commands. .NET provides an interface named ICommand which gives us abilities on a User Action – Invoke and Enabled. ViewModels often provide commands through properties because it provides an option to connect the button to the view model without needing any code in the code behind. It is a good approach if you want a way to enable or disable the availability of command as anyways there will be a property exposed to the view by the view model. So it makes a lot sense to use one property to handle the enabling and invoking a command via one property. Silverlight does not implement icommand. Only button and Hyperlink are able to user ICommand but we need to implement it in our code. Let’s add a new class named RelayCommand inherting from ICommand. This will be the relay the action to the method of our choice. We can also refer this as a delegate command as we use a delegate a to specify the method to invoke. Let’s add the following code to the RelayCommand.

 

Relay Command

Relay Command

  • In the Views folder let’s create new viewmodels. Create a new class named MessageItemViewModel.cs and add the following code to it. It’s the job of the view model to provide the data to be displayed. The all message view model will create one of these for each item in the page. So it will not only require a reference to the model provier but also the particular message which it will wrap. We will add three properties which will extract the MessageAuthor, Message Title, Message Body from the underline model object.

 

MessageItemViewModel

MessageItemViewModel

 

  • Let’s add another ViewModel for all available messages name AllMessagesViewModel. The view model asks the provider for all the available messages and then wraps each one into the message item view model. So that the view can have an items control which can have a list of the items.

 

AllMessagesViewModel

AllMessagesViewModel

  • Now let’s create the View for the ViewModels that we have created. Create a new UserControl named MessageItemView.xaml. let’s first add a reference to ViewModels

xmlns:vm=”clr-namespace:ViewModelSample.ViewModels”

  • Also set the reference of the DataContext to the MessageItemViewModel. The d: here represents that this data context is design time and will not be effective at runtime so we need specify that later as well.

d:DataContext=”{d:DesignInstance vm:MessageItemViewModel}”

  • Now add the following code to the MessageItemView.xaml. This will contain the per message user interface.

 

MessageItemView

MessageItemView

  • Let’s another View which will be the home for the View that we just created. Let’s name this view as AllMessagesView.xaml and add the following code in the xaml. This view just contains a ItemsControl inside scrollviewer and this items control just has a item template as the MessageItemView. It will create an item view for each message item.

 

AllMessagesView

AllMessagesView

  • Also let’s add the following code in the code behind for this.

 

AllMessagesView

AllMessagesView

 

  • Finally add the following code to your MainPage.xaml.

 

MainPage.xaml

MainPage.xaml

 

The code of this post is available here.

 

Any questions, comments or feedback is most welcome.

 

Microsoft has been offering data binding for all its user interface applications but it was an assumption that all the data binding that will happen will always be related to database. However WPF and Silverlight have a broader view assuming that the client side code is often not connected directly to the database. And Silverlight goes a step further by not providing the ADO.NET classes to connect to the database directly. This makes sense because Silverlight is used to design web pages and most organizations do not want to put their database onto the internet for obvious security reasons. So the way data comes into a Silverlight application is in the form of objects or xml. So the data biding framework in Silverlight focuses on objects. So the purpose of data binding is to connect the features of UI to the properties of the objects. Databinding can be used with nearly any property of any element.

Binding Expressions

To bind the property of a user interface element we use the binding markup extension. As you can see in below markup extensions are specified in the curly braces which are evaluated at runtime.

<TextBox Height=”23″ HorizontalAlignment=”Right” Margin=”0,95,22,0″

Name=”textBox2″ VerticalAlignment=”Top” Width=”240″

Text=”{Binding Path=Surname}”/>

 

So this markup binding extension binds the path property of the TextBox to property named Surname and the value of this TextBox text property is evaluated at runtime. Data binding will always connects 2 properties: the target property (generally the user interface property) and the source property (a dependency

Data Context

Now as we saw in the last section that we need to provide the data binding along with the source and target property. So if want to bind multiple targets then we do not need to write the source individually for each of the target property as multiple targets can use the same source for data binding. Let’s have a look at this with an example.

Let’s create a Person class in you user interface with the following Fields as shown below.

namespace DataBindingInSL

{

public class Person

{

public string GivenName { get; set; }

public string Surname { get; set; }

public double Age { get; set; }

}

}

 

Now we want to bind these properties in the User Interface. So lets add the following code in the code behind file of the view.

namespace DataBindingInSL

{

public partial class MainPage : UserControl

{

Person src = new Person { GivenName = “Max”, Surname = “Smith”, Age = 34 };

 

public MainPage()

{

InitializeComponent();

 

this.DataContext = src;

}

}

}

 

Now we are setting the DataContext of the User Interface as src.  By setting the DataContext property at the root element we have made the properties available at the all the elements in the tree as the DataContext in Silverlight cascades down the tree.  We could also set the datacontext on any panel as well and in that case the datacontext will apply only to the panel and its children. Once we have set this DataContext, it becomes the implicit source for all the user Interface elements. So in the View all we need to do is the property name in the binding path and the element will pick up the property from the source i.e. Data Context. Add the following code to the xaml of you SL app.

<Grid x:Name=”LayoutRoot” Background=”White”>

<sdk:Label Height=”23″ HorizontalAlignment=”Left” Margin=”12,38,0,0″ Name=”label1″ VerticalAlignment=”Top” Width=”120″ Content=”Name” />

<TextBox Height=”23″ HorizontalAlignment=”Right” Margin=”0,38,22,0″

Name=”textBox1″ VerticalAlignment=”Top” Width=”240″

Text=”{Binding Path=GivenName}” />

<sdk:Label Height=”23″ HorizontalAlignment=”Left” Margin=”12,95,0,0″ Name=”label2″ VerticalAlignment=”Top” Width=”120″ Content=”Last Name” />

<TextBox Height=”23″ HorizontalAlignment=”Right” Margin=”0,95,22,0″

Name=”textBox2″ VerticalAlignment=”Top” Width=”240″

Text=”{Binding Path=Surname}”/>

<sdk:Label Height=”23″ HorizontalAlignment=”Left” Margin=”12,153,0,0″ Name=”label3″ VerticalAlignment=”Top” Width=”120″ Content=”Age” />

<TextBox Height=”23″ HorizontalAlignment=”Right” Margin=”0,153,22,0″

Name=”textBox3″ VerticalAlignment=”Top” Width=”240″

Text=”{Binding Path=Age}”/>

</Grid>

 

When you run the application you would see that all the TextBox will display the values that are picked up from the bindings.

Data Context Silverlight 4

Data Context Silverlight 4

Right now the data is flowing in only one direction i.e. from src to the User Interface. If we want the data to flow in both the directions then we need to specify the mode as TwoWay in the Binding as shown below:

Text=”{Binding Path=Age, Mode=TwoWay}”

 

Binding Updates

As we saw in the last section that the User interface is updated with the values that are set in source at load time but when the values are updated at a later point in time then also the data binding model of Silverlight can reflect the in the source to the user interface when the data source raises change notification. The change notification can be raised after implementing the INotifyPropertyChanged.

So let’s implement the INotifyPropertyChanged interface in the data source so that whenever the source changes the User Interface is updated along with it as well. This interface has only one event which is raised whenever a property changes in the class. So change the code of the Person class as below along with the implementation of INotifyPropertyChanged.

public class Person : INotifyPropertyChanged

{

public string GivenName { get; set; }

public string Surname { get; set; }

private double _age;

 

public double Age

{

get { return _age; }

set

{

if (value != _age)

{

_age = value;

OnPropertyChanged(“Age”);

}

}

}

 

public event PropertyChangedEventHandler PropertyChanged;

 

private void OnPropertyChanged(string propertyName)

{

if (PropertyChanged != null)

{

PropertyChanged(this, new PropertyChangedEventArgs(propertyName));

}

}

}

 

Here after the implementation of INotifyPropetyChanged we change the code inside the set method of the Age property to call the OnPropertyChanged method which in turn raises the property changed event. So now when the Age property is changed the change will reflect in the User Interface as well. Change the code of the cs and xaml file to as shown below and you will be able to see the update in the property.

 

Silverlight 4 Binding Updates

Silverlight 4 Binding Updates

Data Template

We have seen the example of an adhoc binding in the previous section but Silverlight has a more structured way of defining the same using Data Template. A Data Template is similar to a Control Template. Just as the control Template determines how the Control should like, in a similar way a Data Template determines how the particular data would look like. Data Templates can be used by ItemsControls (ListBox, etc) and ContentControl (Buttons, etc). A Data Template will work at any place where a Content Model is in place.

Whenever there are custom properties in a class then it’s a good idea to define a Data Template in xaml so that the control knows how to display those types.  Let’s see this working in code.

<UserControl.Resources>

<DataTemplate x:Key=”dataTemplateBinding” >

<Grid>

<sdk:Label Height=”23″ HorizontalAlignment=”Left” Margin=”12,38,0,0″

Name=”label1″ VerticalAlignment=”Top” Width=”120″ Content=”Name” />

<sdk:Label Height=”23″ HorizontalAlignment=”Left” Margin=”12,95,0,0″

Name=”label2″ VerticalAlignment=”Top” Width=”120″ Content=”Last Name” />

<sdk:Label Height=”23″ HorizontalAlignment=”Left” Margin=”12,153,0,0″

Name=”label3″ VerticalAlignment=”Top” Width=”120″ Content=”Age” />

<TextBox Height=”23″ HorizontalAlignment=”Right” Margin=”0,38,22,0″

Name=”textBox1″ VerticalAlignment=”Top” Width=”240″

Text=”{Binding Path=GivenName, Mode=TwoWay}” />

<TextBox Height=”23″ HorizontalAlignment=”Right” Margin=”0,95,22,0″

Name=”textBox2″ VerticalAlignment=”Top” Width=”240″

Text=”{Binding Path=Surname, Mode=TwoWay}”/>

<TextBox Height=”23″ HorizontalAlignment=”Right” Margin=”0,153,22,0″

Name=”textBox3″ VerticalAlignment=”Top” Width=”240″

Text=”{Binding Path=Age, Mode=TwoWay}”/>

</Grid>

</DataTemplate>

</UserControl.Resources>

<Grid x:Name=”LayoutRoot” Background=”White”>

<ContentControl Content=”{Binding}”

ContentTemplate=”{StaticResource dataTemplateBinding}” />

<Button Content=”Older” Height=”23″ HorizontalAlignment=”Left” Margin=”43,242,0,0″

Name=”button1″ VerticalAlignment=”Top” Width=”75″ Click=”button1_Click” />

</Grid>

</UserControl>

Binding to Collections

Instead of binding to one instance we can bind a control to a collection. Let’s modify the MainPage as below to create a collection of Person.

public partial class MainPage : UserControl

{

Person src = new Person { GivenName = “Max”, Surname = “Smith”, Age = 34 };

List<Person> people = new List<Person>();

 

public MainPage()

{

InitializeComponent();

 

people.Add(src);

people.Add(new Person { GivenName = “Steve”, Surname=”Gaylon”, Age=44};

people.Add(new Person { GivenName = “John”, Surname=”Miller”, Age=14};

 

this.DataContext = people;

}

 

private void button1_Click(object sender, RoutedEventArgs e)

{

src.Age += 1;

}

}

 

Let’s change the xaml as below:

<UserControl.Resources>

<DataTemplate x:Key=”dataTemplateBinding” >

<Grid>

<sdk:Label Height=”23″ HorizontalAlignment=”Left” Margin=”12,38,0,0″

Name=”label1″ VerticalAlignment=”Top” Width=”120″ Content=”Name” />

<sdk:Label Height=”23″ HorizontalAlignment=”Left” Margin=”12,95,0,0″

Name=”label2″ VerticalAlignment=”Top” Width=”120″ Content=”Last Name” />

<sdk:Label Height=”23″ HorizontalAlignment=”Left” Margin=”12,153,0,0″

Name=”label3″ VerticalAlignment=”Top” Width=”120″ Content=”Age” />

<TextBox Height=”23″ HorizontalAlignment=”Right” Margin=”40,38,22,0″

Name=”textBox1″ VerticalAlignment=”Top” Width=”240″

Text=”{Binding Path=GivenName, Mode=TwoWay}” />

<TextBox Height=”23″ HorizontalAlignment=”Right” Margin=”40,95,22,0″

Name=”textBox2″ VerticalAlignment=”Top” Width=”240″

Text=”{Binding Path=Surname, Mode=TwoWay}”/>

<TextBox Height=”23″ HorizontalAlignment=”Right” Margin=”40,153,22,0″

Name=”textBox3″ VerticalAlignment=”Top” Width=”240″

Text=”{Binding Path=Age, Mode=TwoWay}”/>

</Grid>

</DataTemplate>

</UserControl.Resources>

<Grid x:Name=”LayoutRoot” Background=”White”>

<ListBox ItemsSource=”{Binding}”

ItemTemplate=”{StaticResource dataTemplateBinding}” />

<Button Content=”Older” Height=”23″ HorizontalAlignment=”Left” Margin=”43,242,0,0″

Name=”button1″ VerticalAlignment=”Top” Width=”75″ Click=”button1_Click” />

</Grid>

 

Collection Updates

The INotifyPropertyChange will work only when a property is changed but when a collection is changed we need to implement the INotifyColectionChanged. We can either use ObservalbeCollection<T> or implement this interface to get the update whenever a new item is added to the collection.

Let’s add a new button along with a new event handler to add a new item to the collection so we need to change the xaml and cs file to as below:

private void button2_Click(object sender, RoutedEventArgs e)

{

people.Add(new Person { GivenName = “Scott”, Surname = “D”, Age = 62 });

}

 

<Button Content=”Add Item” Height=”23″ HorizontalAlignment=”Left” Margin=”325,182,0,0″

Name=”button2″ VerticalAlignment=”Top” Width=”75″ Click=”button2_Click” />

 

Now replace the List<Person> with ObservableCollection<Person>.

ObservableCollection<Person> people = new ObservableCollection<Person>();

 

And that is it. Now whenever you click the Add Item button a new item will be added to the collection and also the ListBox will be updated.

 

Grouping

If we want to group the data based on some criteria then we can use the CollectionViewSource. This groups the items based on the property specified of the items.

<UserControl.Resources>
    <CollectionViewSource x:Key="mySource" Source="{Binding Path=RawItems}">
        <CollectionViewSource.GroupDiscussions>
            <PropertyGroupDiscription PropertyName="EventTrack" />
        </CollectionViewSource.GroupDiscussions>
    </CollectionViewSource>
</UserControl.Resources>

 

DataGrid internally understands grouping but the ItemsControl does not. So this is an advantage as by using the ItemsControl we can have our own custom visualizations.

 

Silverlight 4 Grouping

Silverlight 4 Grouping

When we wrap a collection in a collection view source, it provides a property known as groups.  Normally we can bind to a wrapper but we can bind to the groups property instead.

<ItemsControl ItemsSource="{Binding Path=Groups, Source={StaticResource groupSource}}">
    <ItemsControl.ItemTemplate>
            <DataTemplate>
                <ItemsControl ItemsSource="{Binding Path=Items}" />
            </DataTemplate>
        </ItemsControl.ItemTemplate>
</ItemsControl>

Silverlight 4 Grouping

Hierarchical Binding

The basic ability to bind with hierarchical controls is provided by the HeadedItemsControl class. HeadedItemsControl derive from ItemsControl so the binding works in nearly the same way. The difference is in the ItemTemplate property as need to refer to HieraricalDataTemplate instead of a normal DataTemplate. The Hierarchical Data Template has one feature. It too has a ItemsSource Property.

<sdk:HierarchicalDataTemplate ItemsSource="{Binding Path=Children}">
    <TextBlock Text="{Binding Path=Label}" />
</sdk:HierarchicalDataTemplate>

Silverlight 4 Hierarchical Binding

 

Find the source code ralated to this post here.

 

Any questions, comments and feedback are most welcome.

 

File Access Option

In Silverlight there are 3 main ways of accessing files:

  • OpenFileDialog and SaveFileDialog – This is the most flexible of all the file access options as this can be used by any Silverlight application running at any permission level. The user can select any file as long as the user has permissions for the same. The user will have to select the file to read and while saving the user has to specify the filename to override or save as. The code has no permission to know the location of the file and unless the code has elevated permissions the path of the file cannot be known rather only the filename is available. The ability to know the exact path or location is considered to be a security risk by Silverlight. Also these File dialogs are also not allowed until the code for these dialogs is being run in an event handler for user input.
  • FileStream, StreamWriter – The second way is to use the different classes in the System.IO namespace. Silverlight offers classes like File, FileInfo, Directory, DirectoryInfo, FileStream, StreamWriter, etc. In these operations user is not involved. This mode of operation is available only for the trusted application. Not all Silverlight applications can use unless the application is running under elevated privileges.
  • Isolated Storage – A Silverlight application can read or write files to the Isolated Storage without needing the user to be involved. The files can be read or written. The only catch is that the files are saved in the private storage which is under the user directory and the path is not available. So you can just use it as a private store of files where you can access the files. There is no access available for the user files and neither the user can look at the files that are saved unless the user looks into the most of the hidden folder and files under their directory. So the main purpose of Isolated Storage is to provide the application the fast and easy access of files store without user input or elevated trust. But this storage is not reliable as the user can always delete the files.

Let’s have a look at each of these File Access methods in detail:

SaveFileDialog

The SaveFileDialog uses the same file save dialog box supplied by the operating system. To use it we need to create an instance of the SaveFileDialog and call the ShowDialog method. It returns true or false depending on whether the user selected a file or not. The return type of ShowDialog method is nullable bool so we need to compare the return value of the ShowDialog method with true to proceed further with the file selected. However the ShowDialog never returns null but this is the way it is designed. As you can see in the image below once we verify that the user has a selected a filename we can open the file. We can get the filename of the file from the SaveFileName property but the path is not available. So the only way write data is to write the string returned by the dialog.

 

Silverlight 4 : Save File Dialog

Silverlight 4 : Save File Dialog

From the perspective of .Net this is only a string which we can put in a StremWriter to write text into it. If we want to write binary data into it then we can use the Stream Object directly. We can browse to the selected folder and have a look at the saved file.

OpenFileDialog

The OpenFileDialog is similar to the SaveFileDialog. The major difference being  that FileOpenDialog offers a property called multi select which when set to true the user can choose multiple files. So the OpenFileDialog being more complex does not offer a OpenFile method. So depending on whether the OpenFileDialog is in single file or multi file mode we need to use the File or Files property respectively. So as we see in the image below we call File.OpenRead as we are dealing with single file. In the multi select mode we would use the Files property which would return a collection of FileInfo object.

 

Silverlight 4 : Open File Dialog

Silverlight 4 : Open File Dialog

FileStream

The usage of FileStream is quite similar to the regular .NET File access using FileStream. However in Silverlight only application running in elevated trust are allowed to use this technique which is available only in Out of Browser mode. Another restriction in Silverlight is that the files only in specific folder location are available using FileStream. The accessible files are the ones which are in the Users Documents, Music, Pictures and Videos. The reason is because Silverlight runs on multiple platforms and the file system on these platforms might be different and location of these folders might be different on different platforms. We need to use the Enviorment.GetFolderPath method to access these folders. We can also inspect the directory structure beneath these folders using the Directory and DirectoryInfo class in System.IO.

Isolated Storage

It provides storage associated with the logged in user. The API presents data from the stream class from the System.IO namespace. This storage can be used to store either text or binary data. It’s called as Isolated as the storage is partitioned and the Silverlight application have access only to specific parts. Firstly, the storage is partitioned as per the user so that the apps do not have access to the storage space allocated to the other user of the machine. Secondly, the storage is partitioned as per the site and optionally as per the application in the site as well. The partition of the isolated storage depends on the xap files that the apps access. The isolated storage is not dependent on the hosting page. If the multiple pages of an application access the same xap then they will share the same isolated storage. This works for a multi-site website as well. So if multiple sites download the same xap file then the Silverlight supplication will have access to the same Silverlight application isolated store. The Silverlight application provides 1MB of space by default for each user. If the application has more space requirement then it can ask the user for it. Isolated storage is available across browsers on the same machine similar to sharing the cookies across all bowsers, it takes the cross platform support to whole new level.

 

You might be surprised to know that Silverlight is not the pioneer of isolated storage. It was introduced in Widows forms to store data from the web in the partial trust scenarios. Although the method of access is different and there is no way to access the full .Net framework featured Isolated storage.

Now let’s see how to Write to the Isolated storage. Add the following to your Silverlight application.

try

{

//Obtaining the isolated storage from the user

using (IsolatedStorageFile isoStore =

IsolatedStorageFile.GetUserStoreForApplication())

{

//Create new file

using (IsolatedStorageFileStream isoStream =

new IsolatedStorageFileStream(“MyData.txt”,

FileMode.Create, isoStore))

{

//write some content to the file

using (StreamWriter writer = new StreamWriter(isoStream))

{

//Writing line to the file

writer.WriteLine(“Isolated storage is a cool feature”);

}

}

}

}

catch { }

 

As you would see that we need to begin by asking the user specific store for the application. We can also get the user store shared by all the application on the site by calling GetUSerStoreForSite(). The method returns the directory. Then we create an IsolatedStorageFileStream and the constructor requires the IsolatedStorgaeFile as one of the inputs. So here we create a new file in the store but we do not know the location of it. Then we wrap the IsolatedStorageFileStream into a StreamWriter and we write to that file.

Reading from the Isolated storage is very similar with 3 changes. FileMode.Open instaed of FileMode.Create, StreamReader instead on StreamWriter and reader.ReadLine instead of writer.WriteLine.

 

try

{

//Obtaining the isolated storage from the user

using (IsolatedStorageFile isoStore =

IsolatedStorageFile.GetUserStoreForApplication())

{

//Create new file

using (IsolatedStorageFileStream isoStream =

new IsolatedStorageFileStream(“MyData.txt”,

FileMode.Open, isoStore))

{

//write some content to the file

using (StreamReader reader = new StreamReader(isoStream))

{

//Writing line to the file

String sb = reader.ReadLine();

_isolatedStorageReadText.Text = “Read from UserData.txt: ” + sb;

}

}

}

}

catch { }

 

Deleting from the Isolated Storage. To delete the file from the Isolated we do not need to wait on the user. We can use the code below to do that.

try

{

//obtain the Isolated Storage for the user

using (IsolatedStorageFile isoStore =

IsolatedStorageFile.GetUserStoreForApplication())

{

//Delete

isoStore.DeleteFile(“UserData.txt”);

}

}

catch { }

 

Increase the Quota for the Isolated Storage

There is an option for the application to ask for more Isolated Storage space from the user but its not necessary that this space will be provided as its up the user to provide that space. The additional space request should be made at some user input because if its made at any other time then Silverlight will automatically fail the request. This means the extra Quota is only available to the applications with which the user is interacting. The following code can be use to request for additional isolated storage space.

using (var store = IsolatedStorageFile.GetUserStoreForApplication())

{

Int64 spaceToAdd = 5242880;

Int64 curAvail = store.AvailableFreeSpace;

if (curAvail < spaceToAdd)

{

if (!store.IncreaseQuotaTo(store.Quota + spaceToAdd))

MessageBox.Show(“Increase rejected.”);

else

MessageBox.Show(“Increase approved”);

}

else

MessageBox.Show(curAvail.ToString() + “bytes is available”);

}

 

Silverlight 4 : Increase Quota Isolated Storage

Silverlight 4 : Increase Quota Isolated Storage

The users not have the option to wind the quota back as Silverlight does not know which file to trim to remove the quota.

You can download the source code for this file here.

 

Any comments, feedback and questions are most welcome.

Hey guys. Today i am going to discuss about the MediaElement in Silverlight and see how we can put it in use in Silverlight and WPF applications. We can integrate media into our Silverlight pages and WPF UserControls.

 

MediaElement Objects

To add media to the Silverlight page just add a MediaElement to your XAML and provide a URI (Uniform Resource Identifier) to the media to play. The code below will show you how to create a MediaElement and set its Source proprty to URI of a video file. You can add the video file to Visual Studio project also and then set its property to Resource and the MediaElement will begin playing when the page loads.

XAML

<StackPanel Width="300" Height="300">
  <MediaElement x:Name="media" Source="xbox.wmv" Width="300" Height="300" />
</StackPanel>

Note – The MediaElement object can play WMV (Windows Media Video), WMA (Windows Media Audio), MP3 Files.
MediaElement Properties
The MediaElement object provides several media-specific properties. The following list describes the commonly used properties.

  • AutoPlay: Specifies whether the MediaElement should begin playing automatically. The default value is True.
  • IsMuted: Specifies whether the MediaElement is silenced. A value of True mutes the MediaElement. The default value is False.
  • Stretch: Specifies how video is stretched to fill the MediaElement object. Possible values are None, Uniform, UniformToFill, and Fill. The default is Fill.
  • Volume: Specifies the volume of the MediaElement object’s audio as a value from 0 to 1, with 1 being the loudest. The default value is 0.5.

In addition to its media-specific properties, MediaElement also has all the properties of a UIElement, such as Opacity and Clip.

Controlling Media Playback

You can control media playback by using the Play, Pause, and Stop methods of a MediaElement object.

XAML

<Grid>
   <Grid.ColumnDefinitions>
         <ColumnDefinition Width="*" />
         <ColumnDefinition Width="*" />
         <ColumnDefinition Width="*"/>
     </Grid.ColumnDefinitions>
     <Grid.RowDefinitions>
         <RowDefinition Height="*" />
         <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>
    <MediaElement x:Name="media" Source="xbox.wmv" Width="300" Height="300" Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="3" />
    <!-- Stops media playback.-->
     <Button Click="StopMedia" Grid.Column="0" Grid.Row="1" Content="Stop" />
    <!-- Pauses media playback. -->
     <Button Click="PauseMedia" Grid.Column="1" Grid.Row="1" Content="Pause" />
    <!-- Begins media playback. --> 
    <Button Click="PlayMedia" Grid.Column="2" Grid.Row="1" Content="Play" />
</Grid>

 

C#

private void StopMedia(object sender, RoutedEventArgs e)
{
     media.Stop();
}
private void PauseMedia(object sender, RoutedEventArgs e)
{
    media.Pause();
}
private void PlayMedia(object sender, RoutedEventArgs e)
{
    media.Play();
}

Visual Basic

Private Sub StopMedia(ByVal sender As Object, ByVal e As RoutedEventArgs)
     media.Stop() End Sub
Private Sub PauseMedia(ByVal sender As Object, ByVal e As RoutedEventArgs)
     media.Pause() End Sub
Private Sub PlayMedia(ByVal sender As Object, ByVal e As RoutedEventArgs)
     media.Play() End Sub

Video Player Sample with Code

The following example illustrates typical features of a video player including playback control, a progress/seek slider, and full screen toggling.

Smooth Streaming

Smooth Streaming is an IIS (Internet Information Services) technology that enables adaptive streaming over HTTP to Silverlight clients.  Smooth Streaming breaks video feeds into small fragments which enables it to quickly alter the quality of the video, depending on the current bandwidth of the client.  This creates a high-quality viewing experience that scales massively on content distribution networks.   For more information on Smooth Streaming, see the IIS Smoothing Streaming site.

For an indepth example of Smooth Streaming, see the Microsoft Silverlight Media Framework CodePlex project.

 

Extending your Silverlight 4 Application with Controls

We could not only use and extend the controls present in the visual studio toolbox for Silverlight but also there are multiple providers offering additional controls for Silverlight framework.

Extending XAML

XAML stands for eXtensible Application Markup Language and hence it’s possible to add import external elements into a document without breaking rules.

Mapping a Prefix to CLR Namespace

Now we can define a set XML namespace (xmlns) in XML and can map a unique identifier to a prefix so that the XML parser can use additional rules while loading the document.

For Example

Lets say we want to add double value in the document resources. Now as you would know that XAML is by default configured for User Interface elements, the default XML namespaces will not map to Double types so we have to add the line of code shown in Bold in your XAML other than the normal code.

 

<UserControl x:Class="DoubleInResources.MainPage"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

xmlns:sys="clr-namespace:System;assembly=mscorlib"

mc:Ignorable="d"

d:DesignHeight="300" d:DesignWidth="400">

<UserControl.Resources>

<sys:Double x:Key="ButtonsWidth">200</sys:Double>

</UserControl.Resources>

<Grid x:Name="LayoutRoot" Background="White">

<Button Width="{StaticResource ButtonsWidth}" Height="{StaticResource ButtonsWidth}" Content="Click Me!!" />

</Grid>

</UserControl>

 

So we are including the mscorlib namespace which contains the Double type definition and then referencing the same in UserControl.Resources and then we have referenced the same as a static resource.

Note

When we are working with XAML we encounter two types of namespaces

CLR Namespaces – Used in .NET code to group the classes logically.

XML Namespaces – Used to extend XML document with additional declarations.

Prefix is not always needed

Silverlight elements are defined into two namespaces. The first one is a Unique Resource Identifier (URI) mapped to the default xmlns (http://schemas.microsoft.com/winfx/2006/xaml/presentation).

 

In fact, multiple CLR namespaces (such as System.Windows.Controls, System.Windows.Shapes, and so on) are mapped to this URI. This allows us to use all the types within these namespaces without having to use a prefix. For example, we write <Button Click=”Button_Click” /> and not <anyPrefix:Button Click=”Button_Click” />. Note that this URI is not a website’s address, and entering it into a web browser will not lead you anywhere. It is just a Unique Resource Identifier, a unique name.

 

The other namespace used by Silverlight by default is http://schemas.microsoft.com/winfx/2006/xaml, another URI, which is mapped to the x prefix. Inside this namespace are defined additional properties that can be applied to any element.

 

How to add a namespace to any element

You can a namespace mapping to a control as well as shown below:

<Button xmlns:controls=”clr-namespace:MyApplication.Controls”>

<controls:MyControl />

</Button>

 

How to define your own CLR and Mapping CLR Namespaces

We can map our own URI to a group of namespaces and this is useful because we can consolidate multiple CLR namespaces into one single URI and also this would hide the CLR namespaces that our code is using. And later when we decide to move some classes to different CLR namespaces we don’t need to change the XAML code. This is also very useful in creating data objects and it also makes data binding easier.

For Example:

Add the following code to the AssemblyInfo.cs

 

[assembly: XmlnsDefinition("http://www.mycompany.com", "DoubleInResources")]

[assembly: XmlnsDefinition("http://www.mycompany.com", "DoubleInResources.Controls")]

[assembly: XmlnsDefinition("http://www.mycompany.com", "DoubleInResources.DataAccess")]

 

And then after building the solution we can reference it as shown below:

What is a Control?

I know you would say that you know what it is but lets start with a formal definition of Control. A Control is an element of software, encapsulating some functionality related to user interface. Now in Silverlight there are two kinds of controls User Control and Custom Control.

User Controls

A user control is a logical group of other controls. It is typically used to separate a user interface in smaller parts that are easier to code and design. In fact, in Silverlight, all the pages of an application are user controls.

The App class (defined in App.xaml and App.xaml.cs) is the main point of entry for the Silverlight application. This is also where the MainPage control is created and assigned.

The Application_Startup Event Handler in App.xaml.cs is as follows:

 

 

 

If you rename the MainPage control to a different name, you must also change the name in the RootVisual assignment, or else your application will not compile anymore.

 

Custom Controls

The custom controls are made of code only as against XAML (Front End) and a code behind file. All controls build in Silverlight are lookless. The custom control file defines only the controls functionality i.e. Properties and methods and its behavior is defined by its states and parts.

For the controls to be visible, a XAML front end must be defined, though. An invisible control is not very usable! One control can have multiple appearances, defined in as many control templates. We talk out a separation of concerns: The control’s code defines its functionality; the control’s template defines its appearance. Typically, a developer implements the control, whereas a designer styles and templates it.

 

Design a Custom Control

 

Let’s take the example of a Custom with the following functionality:

 

  • The user defines a threshold and a value, both of type Double.
  • If the value is higher than the threshold, the control is in High state.
  • If the value is lower than the threshold, the control is in Low state.
  • If the value is equal to the threshold, the control is in Equal state.
  • Both the threshold and the value can change dynamically, be data bound, animated, and so forth.
  • The user can click one part of the control to increment the value by one unit, and another part to decrement by one unit.
  • The control can be disabled, in which case clicking does not change the value.

 

Now as you see we have the functionality of the custom control but not how the control will look so the developer can start working the designers can do the designing part simultaneously.

 

Let’s get started:

 

  1. In Visual Studio, select File, New, Project from the menu.
  2. In the Add New Project dialog, in the Silverlight category, select Silverlight Class Library.
  3. Enter the name CustomControlsLibrary and click OK. Make sure that you select Silverlight 4 in the next dialog. This creates an assembly, a library that can be referenced in multiple applications but cannot be run on its own.
  4. Delete the file Class1.cs in the Solution Explorer (because will not use it).
  5. Right-click the CustomControlsLibrary project in the Solution Explorer, and select Add, New Item from the context menu.
  6. In the Add New Item dialog, select the Silverlight, and then select a Silverlight Templated Control.
  7. Enter the name ThresholdControl.cs and click Add.

Defining the Parts and States

These steps create a C# code file, a folder named Themes, and a XAML file named

Generic.xaml. We will investigate this last file later; for now let’s declare the parts and

states for this control:

  1. Open the file ThresholdControl.cs.
  2. According to the requirements, the control has two state groups. We will call these the Common states (Normal, Disabled) and the Threshold states (High, Equal, Low). Note that the states within a state group are mutually exclusive; that is, the control cannot be simultaneously in Normal and in Disabled state. However, it can be Normal and High, or Normal and Low, and so forth. Defining the states and states groups is done with the TemplateVisualState attribute on the class.
  3. The requirements also state that the control has two parts with a special meaning: Clicking them increments or decrements the value. Here too, we use an attribute to define the parts on the class: the TemplatePart attribute.

 

The ThresholdControl.cs should look like this

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace CustomControlsLibrary
{
    [TemplatePart(Name = "IncrementPart", Type = typeof(UIElement))]
    [TemplatePart(Name = "DecrementPart", Type = typeof(UIElement))]
    [TemplateVisualState(GroupName = "Common", Name = "Normal")]
    [TemplateVisualState(GroupName = "Common", Name = "Disabled")]
    [TemplateVisualState(GroupName = "Threshold", Name = "High")]
    [TemplateVisualState(GroupName = "Threshold", Name = "Equal")]
    [TemplateVisualState(GroupName = "Threshold", Name = "Low")]
    public class ThresholdControl : Control
    {
        public ThresholdControl()
        {
            this.DefaultStyleKey = typeof(ThresholdControl);
        }

        public double Value
        {
            get
            {
                return (double)GetValue(ValueProperty);
            }
            set
            {
                SetValue(ValueProperty, value);
            }
        }

    public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(double), typeof(ThresholdControl), new PropertyMetadata(0.0, OnValueChanged));

    public double Threshold
    {
        get
        {
            return (double)GetValue(ThresholdProperty);
        }
        set
        {
        SetValue(ThresholdProperty, value);
        }
    }

    public static readonly DependencyProperty ThresholdProperty = DependencyProperty.Register("Threshold", typeof(double), typeof(ThresholdControl), new PropertyMetadata(0.0, OnValueChanged));

    private static void OnValueChanged(object s, DependencyPropertyChangedEventArgs e)
    {
        var sender = s as ThresholdControl;
        if (sender != null)
        {
            sender.GoToThresholdState(true);
        }
    }

    private void GoToThresholdState(bool useTransitions)
    {
        if (Value > Threshold)
        {
             VisualStateManager.GoToState(this, "High", useTransitions);
        }
        else
        {
            if (Value < Threshold)
            {
                 VisualStateManager.GoToState(this, "Low", useTransitions);
            }
            else
            {
                 VisualStateManager.GoToState(this, "Equal", useTransitions);
            }
       }
    }
    
    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();
        var incrementPart = GetTemplateChild("IncrementPart") as UIElement;
        if (incrementPart != null)
        {
            incrementPart.MouseLeftButtonDown += new MouseButtonEventHandler(IncremementPartMouseLeftButtonDown);
        }
        var decrementPart = GetTemplateChild("DecrementPart") as UIElement;
        if (decrementPart != null)
        {
            incrementPart.MouseLeftButtonDown += new MouseButtonEventHandler(DecremementPartMouseLeftButtonDown);
        }
        GoToThresholdState(false);
    }

    void IncremementPartMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        Value++;
    }
    void DecremementPartMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        Value--;
    }
    }
}

 

And the Generic.xaml should look like this:

<ResourceDictionary

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

xmlns:local="clr-namespace:CustomControlsLibrary">

<Style TargetType="local:ThresholdControl">

<Setter Property="Template">

<Setter.Value>

<ControlTemplate TargetType="local:ThresholdControl">

<Border Background="{TemplateBinding Background}"

BorderBrush="{TemplateBinding BorderBrush}"

BorderThickness="{TemplateBinding BorderThickness}">

<VisualStateManager.VisualStateGroups>

<VisualStateGroup x:Name="Threshold">

<VisualState x:Name="High">

<Storyboard>

<DoubleAnimationUsingKeyFrames

Storyboard.TargetProperty="(UIElement.Opacity)"

Storyboard.TargetName="EqualTextBlock">

<EasingDoubleKeyFrame

KeyTime="0" Value="0" />

</DoubleAnimationUsingKeyFrames>

<DoubleAnimationUsingKeyFrames

Storyboard.TargetProperty="(UIElement.Opacity)"

Storyboard.TargetName="LowTextBlock">

<EasingDoubleKeyFrame

KeyTime="0" Value="0" />

</DoubleAnimationUsingKeyFrames>

</Storyboard>

</VisualState>

<!--...-->

</VisualStateGroup>

</VisualStateManager.VisualStateGroups>

<Grid>

<Grid.ColumnDefinitions>

<ColumnDefinition Width="30" />

<ColumnDefinition Width="*" />

<ColumnDefinition Width="30" />

</Grid.ColumnDefinitions>

<Border Background="Blue" x:Name="DecrementPart"

Cursor="Hand">

<TextBlock Text="-" />

</Border>

<StackPanel Grid.Column="1"

Orientation="Vertical"

Margin="10">

<TextBlock Text="{Binding

RelativeSource={RelativeSource TemplatedParent},Path=Value}" />

<TextBlock x:Name="HighTextBlock"

Text="&gt;" />

<TextBlock x:Name="EqualTextBlock"

Text="==" />

<TextBlock x:Name="LowTextBlock"

Text="&lt;" />

<TextBlock Text="{Binding

RelativeSource={RelativeSource TemplatedParent},Path=Threshold}" />

</StackPanel>

<Border Background="Red"

x:Name="IncrementPart"

Grid.Column="2"

Cursor="Hand">

<TextBlock Text="+" />

</Border>

</Grid>

</Border>

</ControlTemplate>

</Setter.Value>

</Setter>

</Style>

</ResourceDictionary>

 

 

You can find the complete Source Code at http://min.us/mKwMNIhKq