Theming in Silverlight

A good design is appreciated if the look and feel is consistent across the application or site you develop. The first and the most best,popular option that comes to our minds is "Themes".

Silverlight allows developers to create rich styles for controls.
Every style has a unique key to identify and it is targeted for a particular element.
To apply style to an element,you have to bind it’s Style property with the unique key of the style defined in the resources at application or local level or defined in resource dictionary.

But is it possible to avoid inline (StaticResource) binding of styles and implicitly apply them to all elements going by the concept of "Themes".
The answer is "YES" and here is the solution. 

How to go about.  ?
In addition to Silverlight library, you will have to install the Silverlight toolkit.
The latest release is here.
There are inbuild themes already available in Silverlight toolkit,but I will create a simple theme from scratch.

Here are the steps:
1) Open Visual Studio and select a Silverlight application.

Silverlight application
2) Add a new folder "Themes" to the project.
Add three Silverlight resource dictionaries each for red,blue and green theme. Set the "Build Action" to Content for each xaml resource file in properties panel ,so that they are added to .xap file and they can be relatively located.

Silverlight resource dictionary       Project structure

Setting the build action to content

 

3) Add reference to "System.Windows.Controls.Theming".
Adding System.Windows.Controls.Theming to the project

4) In MainPage.xaml, I have added a ListBox with names of colors as ListBoxItems.
In a Stackpanel elements like Button,TextBlock and RadioButton have been added.
What I wish to do is on selecting a particular color from ListBox, I want the themes to be applied to all the elements in the StackPanel without StaticResource binding. But first let us create styles for a every element for red,green and blue themes respectively.

Elements in MainPage.xaml file

Code in MainPage.xaml file.

<UserControl x:Class="Themes_Application.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"
    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
  <Grid x:Name="LayoutRoot"  HorizontalAlignment="Center">
        <Grid.RowDefinitions>
            <RowDefinition Height="100"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <ListBox x:Name="lstThemeColor" SelectionChanged="lstThemeColor_SelectionChanged" Width="Auto" BorderBrush="Black" BorderThickness="1" Height="Auto" Grid.Row="0">
            <ListBoxItem Content="Red"/>
            <ListBoxItem Content="Blue"/>
            <ListBoxItem Content="Green"/>
        </ListBox>

        <StackPanel Grid.Row="1" Orientation="Horizontal" x:Name="pnlElements" >
            <Button Height="50" Width="100" Content="Button1" Margin="5"/>
            <Button Height="50" Width="100" Content="Button2" Margin="5"/>
            <Button Height="50" Width="100" Content="Button3" Margin="5"/>
            <TextBlock Text="TextBlock1" Width="Auto" Height="30" Margin="5"/>
            <TextBlock Text="TextBlock2" Width="Auto" Height="30" Margin="5" />
            <RadioButton Content="RadioButton1" Width="Auto" Height="30" Margin="5"/>
            <RadioButton Content="RadioButton2" Width="Auto" Height="30" Margin="5"/>
        </StackPanel>

    </Grid>
</UserControl>

5) The best way to create styles is to copy the xaml code created in Expression Blend after right clicking the element and selecting the "Edit Template" option. Expression Blend provides excellent options to create styles. Change the color properties and edit the states for a particular control. Click here “http://www.silverlight.net/learn/tutorials/stylestemplatesvsm-cs/” to learn how to create styles,templates.
After copy-pasting styles for different colors in resource dictionary, remove the "x:Key" property from every style created  for a particular control as it is not required. Your “RedTheme.xaml ” will look like this. Similary there will be styles created for every type of element in BlueTheme.xaml and GreenTheme.xaml files.

Code in RedTheme.xaml file

6) Once the styles are in place ,we now write the logic to apply it to the elements in the StackPanel. The code is written in MainPage.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;

//this reference is required…
using System.Windows.Controls.Theming;

namespace Themes_Application
{
    public partial class MainPage : UserControl
    {
        Uri uri_resource;
        public MainPage()
        {
            InitializeComponent();
        }

        //on selecting a color value the theme should be applied.
        private void lstThemeColor_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            string color_name = ((ListBoxItem)(lstThemeColor.SelectedItem)).Content.ToString();
            if (color_name == "Red")
            {
                uri_resource = new Uri("Themes/RedTheme.xaml", UriKind.Relative);
            }
            else if (color_name == "Blue")
            {
                uri_resource = new Uri("Themes/BlueTheme.xaml", UriKind.Relative);
            }
            else if (color_name == "Green")
            {
                uri_resource = new Uri("Themes/GreenTheme.xaml", UriKind.Relative);
            }

            //get the theme file and apply it to elements in panel.
            ImplicitStyleManager.SetResourceDictionaryUri(pnlElements, uri_resource);
            ImplicitStyleManager.SetApplyMode(pnlElements, ImplicitStylesApplyMode.Auto);
            ImplicitStyleManager.Apply(pnlElements);
        }
    }
}

Here the ImplicitStyleManager is a class that provides methods to do the following tasks.

a) To first locate the resource dictionary which will apply styles to elements. Here it is the xaml files stored in “Themes” folder
b) To get the name of the parent element in which the child controls or descendants have to be applied styles.
c) To implicitly apply styles to the parent element and its descendants.

Thus without doing any StaticResource binding to any of the elements you can create Themes and apply them implicitly.
Here is the final output in browser.

      Green theme applied

       BlueTheme applied

Red Theme applied

How to consume/connect/use WCF service for Silverlight4 application.

The process is simple. You should know two things,what has to be provided as service.
Where it would be consumed.
Here Windows Communication Foundation lets you create services.
Silverlight application is the client which will consume it.

Steps for creating WCF service:
1) Select a Silverlight application hosted in Web application project.
2) Add to it a WCF service.

Img1
3) Three files will be added to your project.I have chosen the default names.

img2
4) The IService1.cs interface will define the contract and Service1.svc.cs will implement it.

Here MyHello is a simple method to return a message on input of a string.

Code in IService1.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;

namespace Sample1.Web
{
    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        string MyHello(string name);
    }
}

Code in Service1.svc.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;

namespace Sample1.Web
{
    public class Service1 : IService1
    {
        public string MyHello(string name)
        {
            return "Hello "+name+" from WCF service";
        }
    }
}

 
5) Once the service is created build the project and the view the .svc file in browser.

img3

 

Steps for consuming the service.
6) In our Silverlight application,in our xaml page we will add a textbox to enter a name , a button to call WCF service and a textblock to display the output.

img6  

<UserControl x:Class="Sample1.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"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

    <Grid x:Name="LayoutRoot" Background="White">
        <Button Content="Click to call WCF Service" Height="52" HorizontalAlignment="Left"   Margin="44,148,0,0" Name="btn_CallService" VerticalAlignment="Top" Width="320" Click="btn_CallService_Click" />
        <TextBox Height="64" HorizontalAlignment="Left" Margin="44,60,0,0" Name="txt_EnterName" VerticalAlignment="Top" Width="319" />
        <TextBlock Height="52" HorizontalAlignment="Left" Margin="44,222,0,0" Name="txt_DisplayHello" Text="" VerticalAlignment="Top" Width="318" />
    </Grid>
</UserControl>

 
7) Your silverlight application  has to first discover the service created. So add a service reference to your silverlight application project.

 img4

The project structure.

img5
8) Finally the last step. Create a proxy which is an object of ServiceClient to access the method. The methods are loaded asynchronously hence you may not see the name of the method,but two additional methods,one to load method asynchronously and the other to do something once its completed.

 

Code in MainPage.xaml.cs

using System;
using System.Windows;
using System.Windows.Controls;
using System.ServiceModel;

namespace Sample1
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
        }

        private void btn_CallService_Click(object sender, RoutedEventArgs e)
        {
            ServiceReference1.Service1Client proxy = new ServiceReference1.Service1Client();

           //Hooking up the event to display the entered text.
            proxy.MyHelloCompleted +=new EventHandler<ServiceReference1.MyHelloCompletedEventArgs>    (proxy_MyHelloCompleted);

           //Passing the text input
            proxy.MyHelloAsync(txt_EnterName.Text);

        }

     

        void proxy_MyHelloCompleted(object sender, ServiceReference1.MyHelloCompletedEventArgs e)
        {
            txt_DisplayHello.Text = e.Result;
        }

    }
}

9) Its done. Now when you run your application,on click event of button the WCF service will call the function asynchronously to take in the entered text and display the output in textblock.

img7

 

Note: In Silverlight 4 application when using a WCF service I did not have to change the bindings from wsHttpBinding to basicHttpBinding.

Else we had to do it in  earlier versions of Silverlight applications.

Follow

Get every new post delivered to your Inbox.

Join 39 other followers