Quick Silverlight Tip: Define control style dynamically

September 9, 2008

Lately I’ve been asked a couple of time by client how to provide certain level of customization for their Silverlight application. In many cases they want to provide their client with ability to change styles/templates in application or part of it. Another common request, is to provide an ability to use external style definitions. Here the quick tip on how it could be achieved.

I’ll build really simple solution, which uses WebService to provide external style definition as loose XAML file and will apply it to XAML object. Also, my simple solution will receive some style definition as a query string parameter to the page which hosts my application.

First of all my WebService:

   1: [WebMethod]
   2:  public XmlDocument GetStyleDefinition(string styleID)
   3:  {
   4:      //Any styleID to fileName logic could be here...
   5:      if (File.Exists(Server.MapPath("Styles/" + styleID + ".XML")))
   6:      {
   7:          XmlDocument xmlDoc = new XmlDocument();
   8:          xmlDoc.Load(Server.MapPath("Styles/" + styleID + ".XML"));
   9:  
  10:          return xmlDoc;
  11:      }
  12:      else
  13:          return null;
  14:  }

I’m assuming, that “styleID” will be actually the name of XML file with style defintion and it is accessible from the WebService. Any business logic needed to translate style definition could be developed here.

My style definition are simple XML files with style definition for specific control. Example of style definition files:

   1: <Style xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Key="btnTest" TargetType="Button">
   2:   <Setter Property="Background" Value="Yellow"/>
   3:   <Setter Property="FontSize" Value="20"/>
   4:   <Setter Property="FontWeight" Value="Bold"/>
   5:   <Setter Property="Opacity" Value=".8"/>
   6:   <Setter Property="Foreground" Value="Red"/>
   7: </Style>
   1: <Style xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Key="btnTest" TargetType="Button">
   2:   <Setter Property="Background" Value="Red"/>
   3:   <Setter Property="FontSize" Value="25"/>
   4:   <Setter Property="Foreground" Value="Blue"/>
   5: </Style>

Now it’s time to write some XAML… It is very simple in my case – just a grid with one button:

   1: <Grid x:Name="LayoutRoot" Background="White">
   2:     <Button x:Name="btnTest" Content="Test" Click="Test_Click"/>
   3: </Grid>

And now my code behind:

   1: public partial class Page : UserControl
   2: {
   3:     public Page()
   4:     {
   5:         InitializeComponent();
   6:     }
   7:  
   8:     public Page(string StyleName)
   9:     {
  10:         InitializeComponent();
  11:  
  12:         StylesWS.WebServiceSoapClient client = new SilverlightApplication11.StylesWS.WebServiceSoapClient();
  13:         client.GetStyleDefinitionCompleted += new EventHandler<SilverlightApplication11.StylesWS.GetStyleDefinitionCompletedEventArgs>(client_GetStyleDefinitionCompleted);
  14:         client.GetStyleDefinitionAsync(StyleName);
  15:     }
  16:  
  17:     void client_GetStyleDefinitionCompleted(object sender, SilverlightApplication11.StylesWS.GetStyleDefinitionCompletedEventArgs e)
  18:     {
  19:         if (e.Error == null && e.Result != null)
  20:         {
  21:             Style dynStyle = System.Windows.Markup.XamlReader.Load((e.Result as System.Xml.Linq.XElement).ToString()) as Style;
  22:  
  23:             if (null != dynStyle)
  24:                 btnTest.Style = dynStyle;
  25:         }
  26:     }
  27:  
  28:  
  29:     private void Test_Click(object sender, RoutedEventArgs e)
  30:     {
  31:         btnTest.Content = "Clicked";
  32:     }
  33: }

In case of parameterless constructor my Button will remain with default style, otherwise I’m using WebService to get style definition. If WebService not returns the Style the object will be also left intact.

We almost done… All left to me is to receive style definition from InitParams for Silverlight application and pass it while initializing Silverlight object.

Receiving the parameter and initializing relevant constructor done in App.Xaml.cs as a response to application “Startup” event:

   1: private void Application_Startup(object sender, StartupEventArgs e)
   2: {
   3:     if (e.InitParams.Count > 0)
   4:     {
   5:         this.RootVisual = new Page(e.InitParams["Style"].ToString());
   6:     }
   7:     else
   8:         this.RootVisual = new Page();
   9: }

Now my hosting page – if got “Style” parameter pass it to application:

   1: <div id="silverlightControlHost" style="height:100%;width:100%">
   2:       <object data="data:application/x-silverlight," type="application/x-silverlight-2-b2" width="100%" height="100%">
   3:           <param name="source" value="ClientBin/SilverlightApplication11.xap"/>
   4:           <param name="onerror" value="onSilverlightError" />
   5:           <param name="background" value="white" />
   6:           <param name="initParams" value="Style=<%if (null != Request.QueryString["Style"]) Response.Write(Request.QueryString["Style"].ToString());%>"/>
   7:                       
   8:           <a href="http://go.microsoft.com/fwlink/?LinkID=115261" style="text-decoration: none;">
   9:                <img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style: none"/>
  10:           </a>
  11:       </object>
  12:       <iframe style='visibility:hidden;height:0;width:0;border:0px'></iframe>
  13:   </div>

We finished… Now my application will allow customization based on external parameters with external Style definitions:

image image

image image

One very important note on this: Silverlight styles are write once, thus it is not possible to change the style for some object more than one time.

Source code here.

 

Enjoy,

Alex

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

5 comments

  1. KirilSeptember 15, 2008 ื‘ 3:45

    Impressed, excellent article. Hope in the next versions they make the controls change their styles more than once.
    Keep the good work!

    Reply
  2. blogs.microsoft.co.ilApril 3, 2011 ื‘ 9:54

    Quick silverlight tip define control style dynamically.. Ho-o-o-o-t ๐Ÿ™‚

    Reply
  3. blogs.microsoft.co.ilApril 3, 2011 ื‘ 9:54

    Quick silverlight tip define control style dynamically.. Bang-up ๐Ÿ™‚

    Reply
  4. blogs.microsoft.co.ilApril 22, 2011 ื‘ 15:48

    Quick silverlight tip define control style dynamically.. Bully ๐Ÿ™‚

    Reply
  5. blogs.microsoft.co.ilApril 22, 2011 ื‘ 15:48

    Quick silverlight tip define control style dynamically.. Smashing ๐Ÿ™‚

    Reply