Changing CSS with jQuery syntax in Silverlight using jLight
Lately I’ve ran into situations where I had to change elements or had to request a value in the DOM from Silverlight. jLight, which was introduced in an earlier article, can help with that. jQuery offers great ways to change CSS during runtime. Silverlight can access the DOM, but it isn’t as easy as jQuery. All examples shown in this article can be looked at in this online demo. The code can be downloaded here.
Part 1: The easy stuff
Selecting and changing properties is pretty straight forward. Setting the text color in all <B> </B> elements can be done using the following code:
jQuery.Select("b").Css("color", "red");
The Css() method is an extension method on jQueryObject which is return by the jQuery.Select() method. The Css() method takes to parameters. The first is the Css style property. All properties used in Css can be entered in this string. The second parameter is the value you want to give the property. In this case the property is “color” and it is changed to “red”.
To specify which element you want to select you can add a :selector parameter to the Select() method as shown in the next example.
jQuery.Select("b:first").Css("font-family", "sans-serif");
The “:first” pseudo-class selector selects only the first element. This example changes the “font-family” property of the first <B></B> element to “sans-serif”.
To make use of intellisense in Visual Studio I’ve added a extension methods to help with the pseudo-classes.
In the example below the “font-weight” of every “Even” <LI></LI> is set to “bold”.
jQuery.Select("li".Even()).Css("font-weight", "bold");
Because the Css() extension method returns a jQueryObject it is possible to chain calls to Css(). The following example show setting the “color”, “background-color” and the “font-size” of all headers in one go.
jQuery.Select(":header").Css("color", "#12FF70")
.Css("background-color", "yellow")
.Css("font-size", "25px");
Part 2: More complex stuff
In only a few cases you need to change only one style property. More often you want to change an entire set op style properties all in one go. You could chain a lot of Css() methods together. A better way is to add a class to a stylesheet and define all properties in there. With the AddClass() method you can set a style class to a set of elements. This example shows how to add the “demostyle” class to all <B></B> in the document.
jQuery.Select("b").AddClass("demostyle");
Removing the class works in the same way:
jQuery.Select("b").RemoveClass("demostyle");
jLight is build for interacting with to the DOM from Silverlight using jQuery. A jQueryObjectCss object can be used to define different sets of style properties in Silverlight. The over 60 most common Css style properties are defined in the jQueryObjectCss class. A string indexer can be used to access all style properties ( CssObject1[“background-color”] equals CssObject1.BackgroundColor). In the code below, two jQueryObjectCss objects are defined and instantiated.
private jQueryObjectCss CssObject1;
private jQueryObjectCss CssObject2;
public Demo2()
{
CssObject1 = new jQueryObjectCss
{
BackgroundColor = "Lime",
Color="Black",
FontSize = "12pt",
FontFamily = "sans-serif",
FontWeight = "bold",
MarginLeft = 150,
LineHeight = "28px",
Border = "Solid 1px #880000"
};
CssObject2 = new jQueryObjectCss
{
FontStyle = "Italic",
FontSize = "48",
Color = "#225522"
};
InitializeComponent();
}
Now instead of chaining to set all different properties you can just pass one of the jQueryObjectCss objects to the Css() method. In this case all <LI></LI> elements are set to match this object.
jQuery.Select("li").Css(CssObject1);
When using the jQueryObjectCss objects chaining is still possible. In the following example all headers are given a blue backgroundcolor and the last is set to match CssObject2.
jQuery.Select(":header").Css(new jQueryObjectCss{BackgroundColor = "Blue"})
.Eq(-1).Css(CssObject2);
Part 3: The fun stuff
Having Silverlight call JavaScript and than having JavaScript to call Silverlight requires a lot of plumbing code. Everything has to be registered and strings are passed back and forth to execute the JavaScript. jLight makes this kind of stuff so easy, it becomes fun to use. In a lot of situations jQuery can call a function to decide what to do, setting a style class based on complex expressions for example. jLight can do the same, but the callback methods are defined in Silverlight.
This example calls the function() method for each <LI></LI> element. The callback method has to take a jQueryObject, an integer and a string as parameters. In this case jLight differs a bit from the actual jQuery implementation. jQuery uses only the index and the className parameters. A jQueryObject is added to make it simpler to access the attributes and properties of the element.
If the text of the listitem starts with a ‘D’ or an ‘M’ the class is set. Otherwise null is returned and nothing happens.
private void button1_Click(object sender, RoutedEventArgs e)
{
jQuery.Select("li").AddClass(function);
}
private string function(jQueryObject obj, int index, string className)
{
if (obj.Text[0] == 'D' || obj.Text[0] == 'M')
return "demostyle";
return null;
}
The last thing I would like to demonstrate uses even more Silverlight and less jLight, but demonstrates the power of the combination. Animating a style property using a Storyboard with easing functions. First a dependency property is defined. In this case it is a double named Intensity. By handling the changed event the color is set using jQuery.
public double Intensity
{
get { return (double)GetValue(IntensityProperty); }
set { SetValue(IntensityProperty, value); }
}
public static readonly DependencyProperty IntensityProperty =
DependencyProperty.Register("Intensity", typeof(double), typeof(Demo3),
new PropertyMetadata(0.0, IntensityChanged));
private static void IntensityChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var i = (byte)(double)e.NewValue;
jQuery.Select("span").Css("color", string.Format("#{0:X2}{0:X2}{0:X2}", i));
}
An animation has to be created. This code defines a Storyboard with one keyframe that uses a bounce ease as an easing function. The animation is set to target the Intensity dependency property defined earlier.
private Storyboard CreateAnimation(double value)
{
Storyboard storyboard = new Storyboard();
var da = new DoubleAnimationUsingKeyFrames();
var d = new EasingDoubleKeyFrame
{
EasingFunction = new BounceEase(),
KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1.0)),
Value = value
};
da.KeyFrames.Add(d);
Storyboard.SetTarget(da, this);
Storyboard.SetTargetProperty(da, new PropertyPath(Demo3.IntensityProperty));
storyboard.Children.Add(da);
return storyboard;
}
Initially the Intensity is set to 128 which results in a gray color. When one of the buttons is pressed, a new animation is created an played. One to animate to black, and one to animate to white.
public Demo3()
{
InitializeComponent();
Intensity = 128;
}
private void button2_Click(object sender, RoutedEventArgs e)
{
CreateAnimation(255).Begin();
}
private void button3_Click(object sender, RoutedEventArgs e)
{
CreateAnimation(0).Begin();
}
Conclusion
As you can see jLight can make the life of a Silverlight developer a lot easier when accessing the DOM. Almost all jQuery functions that are defined in jLight use the same constructions as described above. I’ve tried to stay as close as possible to the real jQuery. Having JavaScript perform callbacks to Silverlight using jLight will be described in more detail in a future tutorial about AJAX or eventing.
Introducing jLight – Talking to the DOM using Silverlight and jQuery.
Introduction
With the recent news about Silverlight on the Windows Phone and all the great Out-Of-Browser features in the upcoming Silverlight 4 you almost forget Silverlight is a browser plugin. It most often runs in a web browser and often as a control. In many cases you need to communicate with the browser to get information about textboxes, events or details about the browser itself. To do this you can use JavaScript from Silverlight. Although Silverlight works the same on every browser, JavaScript does not and it won’t be long before problems arise. To overcome differences in browser I like to use jQuery. The only downside of doing this is that there’s a lot more code needed that you would normally use when you write jQuery in JavaScript.
Lately, I had to catch changes is the browser scrollbar and act to the new position. I also had to move the scrollbar when the user dragged around in the Silverlight application. With jQuery it was peanuts to get and set the right attributes, but I found that I had to write a lot of code on Silverlight side. With a few refactoring I had a separated out the plumbing into a new class and could call only a few methods on that to get the same thing done. The idea for jLight was born.
jLight vs. jQuery
The main purpose of jLight is to take the ease of use of jQuery and bring it into Silverlight for handling DOM interaction. For example, to change the text color of a DIV to red, in jQuery you would write:
jQuery("div").css("color","red");
In jLight the same thing looks like so:
jQuery.Select("div").Css("color","red");
Another example. To change the offset in of the last SPAN you could write this in jQuery :
jQuery("span:last").offset({left : 10, top : 100});
In jLight this would do the same:
jQuery.Select("span:last").Offset(new {left = 10, top = 100 });
Callbacks
Nothing too special so far. To get the same thing done using the “normal” HtmlPage.Window.Eval, it wouldn’t require too much effort. But to wire up a handler for events from the browser it’s a whole different story. Normally you need to register ScriptMembers, ScriptableTypes or write some code in JavaScript. jLight takes care of the plumbing and provide you with an simple interface in the same way jQuery would.
If you would like to handle the scroll event of the BODY of your html page, you’ll have to bind the event using jQuery and have a function call back to a registered function in Silverlight. In the example below I assume there’s a method “SomeMethod” and it is registered as a ScriptableObject as “RegisteredFromSilverlight” from Silverlight.
jQuery("body:first").scroll(function()
{
var sl = document.getElementbyId("SilverlightControl");
sl.content.RegisteredFromSilverlight.SomeMethod($(this));
});
Using jLight in Silverlight the code would be even simpler. The registration of RegisteredFromSilverlight as ScriptableObject can be omitted. Besides that, you don’t have to write any JavaScript or evaluate strings with JavaScript.
jQuery.Select("body:first").scroll(SomeMethod);
Lambdas
Using a lambda in Silverlight can make it even simpler. Each is the jQuery equivalent of foreach in C#. It calls a function for every element found by jQuery. In this example all INPUT elements of the text type are selected. The FromObject method is used to create a jQueryObject from an object containing a ScriptObject. The Val method from jQuery is used to get the value of the INPUT elements.
jQuery.Select("input:text").Each((element, index) =>
{
textBox1.Text += jQueryObject.FromObject(element).Val();
return null;
});
Ajax
One thing jQuery is often used for is making Ajax calls. Making calls to services to external services can be done from Silverlight, but as easy as using jQuery. As an example I would like to show how jLight does this. Below is the entire code behind. It searches my name on twitter and shows the result. This example can be found in the source of the project. The GetJson method passes a Silverlight JsonValue to a callback. This callback instantiates Twit objects and adds them to a ListBox called TwitList.
public partial class DemoPage2 : UserControl
{
public DemoPage2()
{
InitializeComponent();
jQuery.Load();
}
private void CallButton_Click(object sender, RoutedEventArgs e)
{
jQuery.GetJson("http://search.twitter.com/search.json?lang=en&q=sorskoot",
Done);
}
private void Done(JsonValue arg)
{
var tweets = new List<Twit>();
foreach (JsonObject result in arg["results"])
{
tweets.Add(new Twit()
{
Text = (string)result["text"],
Image = (string)result["profile_image_url"],
User = (string)result["from_user"]
}
);
}
TwitList.ItemsSource = tweets;
}
}
public class Twit
{
public string User { get; set; }
public string Image { get; set; }
public string Text { get; set; }
}
Conclusion
Although jLight is still in development it can be used already.There isn’t much documentation yet, but if you know jQuery jLight isn’t very hard to use. If you would like to try it, please let me know what you think and report any problems you run in to.
A demo of accessing text elements can be found here. The Twitter demo can be found here.
jLight itself can be found at:


