Recently, I was learning about Silverlight
for a project. Here is what I’m keeping for future reference:
A Microsoft platform for developing and deploying Rich internet applications. Right now, it’s a depreceated technology. Runs as a browser plugin. Supports .NET languages like C#
and VB.NET
, IronPython
and IronRuby
using DLR (Dynamic Language Runtime).
There’re 3 options:
We also need to install the Silverlight SDK.
C#
-> Silverlight
If the developer runtime for Silverlight
is not installed, the following popup will be shown
When running the project, in case the Silverlight
is not installed in the browser, the following browser notification will be shown:
Clicking the install link will take us to the Microsoft website for downloading and installing the plugin
From the VS main menu’s Tools -> Options
word warp
and line number
under General nodeTab
and indent size
to 2 under Tabs node. Also keep tabsThere are two types of Microsoft Silverlight assemblies:
The core Silverlight assemblies
mscorlib.dll
System.Core.dll
system.dll
System.Net.dll
System.Windows.dll
SDK assemblies, which are used for additional functionalities.
Path in web
setting specifies where to put the output .xap
files. In the image shown, it’s ClientBin
folder.
The initial / startup control can be set from App.xaml.cs
.
The Silverlight application is compiled into a .dll
which is then used by the Silverlight runtime.
The .csproj
file contains the build instructions. During build, VS executes the build instructions contained in the .csproj
file. One of the instructions calls the language compiler such as csc.exe
for C#
, vbc.exe
for VB.NET
Although the process is build, a lot of devs call it compiling.
With Solution configuration set to Debug
, the Visual studio will create a Debug
folder inside the Bin
folder of the project. In general cases, there will be 5 files
AppManifest
file - contains the application information.dll
file - the actual code which will be loaded by the Silverlight runtime when executing the project.pdb
file - the portable debug file for the project.xap
file - the zipped bundle of AppManifest
and the application .dll
s. This is useful in cases when the application uses SDK assemblies. The zip bundle will help the client download the SDK .dll
s.html
file - the application test file generated by the Properties
-> Debug
-> Start Action
set to Dynamically generate a test page
When doing the deployment, the mime types need to be mapped in IIS by following the below steps:
Mime Types
and the entries as shown below:.xap
-> application/x-silverlight
- For Silverlight 1 and later .xap
-> application/x-silverlight-2
(-2 means the second implementation of the mime type) - For Silverlight 2 to 5 .xaml
-> ‘application/xaml+xml’
When the application starts up, the Test
HTML page (generated inside the Bin
folder) asks the browser to load the Silverlight plugin which is specified in the following tag:
<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">
The browser plugin then later asks for the .xap
file. Which is basically a .zip
folder containing application and other .dlls
with information inside the application manifest file.
To not allow browser to load the default error page when the Silverlight plugin isn’t available, set the object
tag’s autoUpgrade
parameter to false
<param name="autoUpgrade" value="false" />
with url set to the download link of the required Silverlight plugin. The javascript onSilverlightError
needs to be used. The ErrorCode
to watch for is 8001
:
function onSilverlightError(sender, args) {
if (args.ErrorCode == 8001) {//code to run when correct Silverlight plugin version isn't available}}
The Silverlight code behind files are in partial
classes (one holding the event handling, another for the UI handling). Using a XAML
element is equal to instantiating a .NET
class. The XML
elements are validated against xml namespaces.
To assign run time calculation of value and assing to a property we need to use Markup extensions. These classes do binding and resource lookup.
When we assign a property in XAML, we’re passing a
Passing values at compile time
<TextBox Text='abc' Background='Orange' />
Passing values at run time
<TextBox Text='{local:LatinWords}' Background='{StaticResource warning}' />
Types of data binding in XAML are:
<!-- Make this element idenfiable by name --><TextBox Text='Hello' x:Name='textHello' Background='Goldenrod' /><!-- Assign value from the above textHello to this element --><TextBox Text='Goodbye' Background='{Binding ElementName=textHello, Path=Background}' />
<!-- Read value red from Text property and assign it to Background property --><TextBox Text='Red' Background='{Binding Text, RelativeSource={RelativeSource Self }}' />
<!-- Define a static resource --><LinearGradientBrush x:Key='seaBrush'><LinearGradientBrush.GradientStops><GradientStop Offset="0" Color="Yellow" /><GradientStop Offset="0.5" Color="Orange" /><GradientStop Offset="0.8" Color="LightCoral" /></LinearGradientBrush.GradientStops></LinearGradientBrush>
<!-- use the seaBrush static resource for the Background property --><TextBox Text='StaticResource' Background='{StaticResource seaBrush}' />
<!-- Null MarkupExtension --><TextBox Text='Null MarkupExtension' Background='{x:Null}' />
<!-- The XML namespace abc is defined which refers to abcLib in UserControl --><UserControl xmlns:abc='clr-namespace:abcLib;assembly=abcLib' >
... rest of the code ...
<!-- use our custom markup extension--><TextBox Text='{abc:LatinWords WordCount=5}' Background='{x:Null}' /></UserControl>
and the implementation of custom markup extension is:
namespace abcLib{public class LatinWords : IMarkupExtension<string>{
public bool RandomStartPoint { get; set; }public int WordCount { get; set; }
private Int32 _numberOfWords;private static Random ran = new Random();private string[] _words;
public void SetupWords(){// for demo limit the number of words to 100if (WordCount <= 1){_numberOfWords = 1;}if (_numberOfWords > 100){_numberOfWords = 100;}else{_numberOfWords = WordCount;}
_words = _sourceString.Split(' ');
}public string ProvideValue(IServiceProvider serviceProvider){SetupWords();int skipCount = 0;if (this.RandomStartPoint){skipCount = ran.Next(3, 20);}return string.Join(" ", _words.Skip(skipCount).Take(_numberOfWords).ToArray());}
private string _sourceString = "Lorem ipsum. ";
}}
Silverlight uses a unique property system which was invented by WPF team. This provides services for UI like Animation, Templates, Styles and reduces critical resource usage (e.g. memory). It has two parts:
When creating own user controls, dependency property (e.g. on Button element: FontSize) and .NET property both are correct ways to expose a property on them.
Value resolution priorities
Case:
local value
for a property is set to 20 and the control in concern is getting animated changing property value from 40 to 80Setting dependency properties using code:
In XAML
file
<Button x:Name='sampleButton' Content='Set the Properties in Code' Click='sampleButton_Click' />
In code behind
private void sampleButton_Click(object sender, RoutedEventArgs e){sampleButton.FontSize = 40; // using a .NET wrapper to set value
double size = sampleButton.FontSize; // use the .NET wrapper to read value
// use the DP system directly
sampleButton.SetValue(FontSizeProperty, 30);size = (double)sampleButton.GetValue(FontSizeProperty);
}
Silverlight elements and controls (default or custom) have lots of dependency properties. This system provides services such as animation, data binding, control templates and styles to the Silverlight elements.To get these services a developer needs to write ‘ugly’ registration code.
An example of declaring and registering a dependency property is:
public partial class StarShape : UserControl {
public StarShape(){InitializeComponent();}
//declaringpublic static readonly DependencyProperty PointsProperty;
//registeringstatic StarShape(){
// 2. Register with the DP systemPointsProperty = DependencyProperty.Register("Points", typeof(double), typeof(StarShape), null);
}}
Notice that the property is declared readonly, which means it can only be instantiated in it’s static constructor.
They are a special dependency property to provide decoupled extensible model. We can think of it as a ‘global property’ meaning it is available to all controls in Silverlight runtime.
It is owned and registered by a Type. The method for the same is DependencyProperty.RegisterAttached
. It uses the dotted syntax TypeName.AttachedProperty
. These properties are mostly used in layout panels Canvas, Grid, DockPanel.
Key points:
Originally published at xameeramir.github.io.