XAML Playground
about XAML and other Amenities

A bit of Physics for an InertialScrollViewer

2009-05-10T01:22:27+01:00 by Andrea Boschin

Silverlight 2.0 and 3.0 come with an useful control called ScrollViewer, that helps when long list of elements needs to be scrolled with a traditional scrollbar. New mobile devices like the iPhone introduced a new kind of ScrollViewer where the user only needs to use his thumb to move the lists of elements on the screen. This beautiful kind of ScrollViewer often give an impressive feedback with a fluid scrolling that ends in a real soft deceleration giving the impression that the bend of elements is subject to the physics rules. This is not only scenic, but give the user a natural feedback that take usability to the maximum levels. So, in this article I would want to illustrate how to apply some simple physics formula to create a reusable InertialScrollViewer to take this feedback into Silverlight applications.

Please note that I'm not a physicist. I have only searched my school notions and tried to get something to work. And it works fine as you will see... :)

How the control has to work

Before entering the coding phase of the control, we need to understand how the control has to work. From the developer perspective the InertialScrollViewer must work similar to the original ScrollViewer. It have to scroll the content generated inside of it and let the user scroll Vertically or Horizontally. My implementation of this control let the developer to choice if scroll Vertically or Horizontally but not in both the directions at the same time.

From the user perspective we have two different phases: when the user click on the band he can move it using the mouse (e.g from left to the right). While the user is moving, the band is simply locked to the mouse and if the user stop scrolling the bend also stops. Only when the user leave the mouse button while he is scrolling, it has to maintain the current speed and decrease it to zero in a variable distance. The calculation of the speed is the most difficult thing, infact we have to take note of the change of direction and not only of the difference from the starting point to the end of the scrolling. If the user start scrolling from left to right and at a given point stops he turn scrolling from the right to left, the speed needs to be recalculated from the direction change and not from the start of the scrolling action. To avoid this kind of problems I decided to sample the speed at every MouseMove event. Every time this event will be raised I take note of "ticks" and "distance" from the previous event and calculate the speed with the simple formula

speed = distance / time

For a better precision I record the last two samples and when the user leave the mouse button I calculate the medium of the two available samples.

The other phase of the user interaction enter when the user stop dragging and the band start decrease its speed. All calculation is done when this event occur. First we have to calculate the distance that the band will race with the starting speed and then we have to calculate how much time it take to decrease speed to zero. The first part use this formula:

distance = speed ^ 2 / 20 * f

This formula, I found in my physics schoolbook, use f as friction factor to determine the type of surface where the bend is moving. A number less then 0.5 determine a slippery surface so the bend will run a long distance. A number from .5 to 1 determine a rough surface. This value is exposed by my control so the developer can change it and give different feedback to the user.

To calculate the time needed for the bend going from the start speed to zero I found another formula that get a deceleration value. Here is the formula

time = -speed / -a 

Where "-a" is the negative acceleration. This formula result from a more complicated formula that I've simplified due to some 0 occurrence. The simplification process is out of the scope of this article.

Now that we have all calculation done, it is time to start implementing the control.

The InertialScrollViewer ControlTemplate

The first thing to do is implementing a templated control. Like every control in Silverlight the InertialScrollViewer will take advantage of a template that will be saved in Themes/generic.xaml. Here we cannot inherit from the ScrollViewer control because it is sealed so our custom scroller will be a ContentControl and it allow to scroll content put into itself.

The template or the InertialScrollViewer is made of a Border containing a Canvas and then a ContentControl. I put some defaults to give the InertialScrollViewer an appearance similato to the original ScrollViewer. Here is the template:

   1: <Style TargetType="local:InertialScrollViewer">
   2:         <Setter Property="Padding" Value="0"/>
   3:         <Setter Property="Background" Value="#FFFFFFFF"/>
   4:         <Setter Property="BorderThickness" Value="1"/>
   5:         <Setter Property="VerticalContentAlignment" Value="Stretch"/>
   6:         <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
   7:         <Setter Property="BorderBrush">
   8:             <Setter.Value>
   9:                 <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
  10:                     <GradientStop Color="#FFA3AEB9" Offset="0"/>
  11:                     <GradientStop Color="#FF8399A9" Offset="0.375"/>
  12:                     <GradientStop Color="#FF718597" Offset="0.375"/>
  13:                     <GradientStop Color="#FF617584" Offset="1"/>
  14:                 </LinearGradientBrush>
  15:             </Setter.Value>
  16:         </Setter>
  17:         <Setter Property="Template">
  18:             <Setter.Value>
  19:                 <ControlTemplate>
  20:                     <Border x:Name="RootElement" 
  21:                             CornerRadius="2"                            
  22:                             Padding="{TemplateBinding Padding}"
  23:                             Background="{TemplateBinding Background}"
  24:                             BorderBrush="{TemplateBinding BorderBrush}" 
  25:                             BorderThickness="{TemplateBinding BorderThickness}">
  26:                         <Border.Resources>
  27:                             <Storyboard x:Name="EasingStoryboard">
  28:                                 <DoubleAnimation />
  29:                             </Storyboard>
  30:                         </Border.Resources>
  31:                         <Canvas x:Name="CanvasElement">
  32:                             <ContentControl x:Name="ContentElement"
  33:                                             Content="{TemplateBinding Content}"
  34:                                             VerticalAlignment="Stretch"
  35:                                             HorizontalAlignment="Stretch"
  36:                                             VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
  37:                                             HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" />
  38:                         </Canvas>
  39:                     </Border>
  40:                 </ControlTemplate>
  41:             </Setter.Value>
  42:         </Setter>
  43:     </Style>

The <Border /> "RootElement" inside the template will be the outer border of the control. It receive the default values and have a shaded BorderBrush. It contains a StoryBoard into its resources. I will return on it later in the article.

The <Canvas /> "CanvasElement" is required to be able to scroll the ContentControl I put inside of it. After doing some tests I found that the Canvas is the only control that let me apply some Transform to the ContentControl and continue to show the content without any clipping. People using the control will have no knowledge about the Canvas.

Finally the ContentControl has been configured to let the content stretch to fill all the available space. Its VerticalContentAlignment and HorizontalContentAlignment property has been binded to the corresponding template properties so the user can configure the control behavior.

Let's do some code...

Now it is time to start coding. The control is about 300 line long so it is impossible to explain all the code. I will explain the key point following the control lifetime. After doing some inizialization in the control constructor the first place where it is required we write some code is the OnApplyTemplate method. Inside this method we have to hook every element of our template. The elements will be assigned to some member properties using the GetTemplateChild method. To let the control customizable I have also specified the TemplatePart attributes on top of the class. Here is the parts:

   1: [TemplatePart(Name = InertialScrollViewer.RootElementName, Type = typeof(Border))]
   2: [TemplatePart(Name = InertialScrollViewer.CanvasElementName, Type = typeof(Canvas))]
   3: [TemplatePart(Name = InertialScrollViewer.ContentElementName, Type = typeof(ContentControl))]
   4: [TemplatePart(Name = InertialScrollViewer.EasingStoryboardName, Type = typeof(Storyboard))]

Every element has its own wrapping constant to centralize the names in a single point. During the OnApplyTemplate this names will be used to pick up the elements and assign to the corresponding properties. I also create a TranslateTransform into this method and assign it to the RenderTransform property of the ContentControl. The reason to create the TranslateTransform - used to scroll the content - is that if the user customize it can easily break the control functionality.

   1: public override void OnApplyTemplate()
   2: {
   3:     // Border
   4:     this.RootElement = GetTemplateChild(InertialScrollViewer.RootElementName) as Border;
   5:  
   6:     // Canvas
   7:     this.CanvasElement = GetTemplateChild(InertialScrollViewer.CanvasElementName) as Canvas;
   8:     this.CanvasElement.SizeChanged += new SizeChangedEventHandler(CanvasElement_SizeChanged);
   9:  
  10:     // clip the content to the Width and Height
  11:     this.CanvasElement.Clip =
  12:         this.CanvasClipping = new RectangleGeometry
  13:         {
  14:             Rect = new Rect(0, 0, this.CanvasElement.ActualWidth, this.CanvasElement.ActualHeight)
  15:         };
  16:  
  17:     // ContentControl
  18:     this.ContentElement = GetTemplateChild(InertialScrollViewer.ContentElementName) as ContentControl;
  19:     this.ContentElement.RenderTransform =
  20:         this.Translate = new TranslateTransform { X = 0, Y = 0 };
  21:  
  22:     this.ContentElement.MouseLeftButtonDown += (a, b) => this.HandleMouseDown(this.GetMousePosition(b, this.Orientation));
  23:     this.ContentElement.MouseLeftButtonUp += (a, b) => this.HandleMouseUp(this.GetMousePosition(b, this.Orientation));
  24:     this.ContentElement.MouseMove += (a, b) => this.HandleMouseMove(this.GetMousePosition(b, this.Orientation));
  25:  
  26:     // StoryBoard
  27:     this.EasingStoryboard = this.RootElement.Resources[InertialScrollViewer.EasingStoryboardName] as Storyboard;
  28:     this.EasingAnimation = this.EasingStoryboard.Children.OfType<DoubleAnimation>().FirstOrDefault();
  29:  
  30:     // let do some inizialization
  31:     this.OnOrientationChanged(this.Orientation);
  32:     this.OnEasingFunctionChanged(this.EasingFunction);
  33:  
  34:     // and call the base class
  35:     base.OnApplyTemplate();
  36: }

The last thing to take note is the Clipping. The Canvas is a control that do not have a frame. The content can be put at negative coordinates but it is not clipped if there is some space available. So I have created a RectangleGeometry and I use it to clip the Canvas at his ActualWidth and ActualHeight. This is done in the CanvasElement_SizeChanged event handler every time the size of the element will be changed.

During the OnApplyTemplate method I attach some event handlers to the ContentControl to handle the Mouse events MouseMove, MouseLeftButtonDown and MouseLeftButtonUp. This events let me know when the user try to scroll the content.

In the MouseLeftButtonDown I do some inizialization. I Capture the mouse, inizializa the Translation and then start the sampling using an instance of the SpeedSample class. In the MouseMove I do the sampling using the same specialized class SpeedSampler. The SpeedSampler class is responsible to count the incoming events from MouseMove and record the last two samples. In my opinon the class is pretty simple and do not need any explanation. In the same event I also apply the value to the TranslateTransform to move the content to the required position.

When the user leave the mouse button the flow goes to the MouseLeftButtonUp event handler and inside of it I do alle the required calculation. First of all I take note of the current speed and then I calculate the distance and the duration of the deceleration.

   1: /// <summary>
   2: /// Handles the mouse up.
   3: /// </summary>
   4: /// <param name="mousePosition">The mouse position.</param>
   5: private void HandleMouseUp(double mousePosition)
   6: {
   7:     if (this.GetBoundary(this.Orientation) >= 0) return;
   8:  
   9:     this.IsCaptured = false;
  10:     this.ContentElement.ReleaseMouseCapture();
  11:     double speed = this.Sampler.GetSpeed();
  12:  
  13:     if (this.EasingStoryboard != null && this.EasingAnimation != null)
  14:     {
  15:         this.EasingAnimation.To = this.ComputeNextPosition(Math.Pow(speed, 2) / (20 * this.FrictionFactor) / 1000 * this.Sampler.Direction);
  16:         this.EasingAnimation.Duration = TimeSpan.FromSeconds(-(speed / 1000) / -this.Deceleration);
  17:         this.EasingStoryboard.Begin();
  18:     }
  19: }

Once I have calculated this parameters the only thing I have to do is to assign them to the Storyboard and start the animation. The EasingStoryboard has been picked up from the template and will run the scroller to its calculated end position. If the user will click on the content during the easing animation I simply stop the animation and forget all the calculation.

The Storyboard has a default QuadraticEasing function applied that to me is the better choice to give a natural behavior. The control expose an EasingFunction property to let the user cutomize the animation easing. Putting and ElasticEase give the control an astounding elastic behavior.

The control expose some other properties to let the user customize it. Orientation let you decide if scrolling is vertical or horizontal. FrictionFactor and Deceleration let customize the physics parameters. I suggest you to try by yourself changing the properties and the easing to give the control the preferred behavior.

Some final words.

Attached to this article you will find the complete source of the control. I would like to have your feedback about how it works. I made many tests and to me it is working fine but I'm sure that it is not perfect. If you find some strange behavior please post a comment and I will try to get rid of it.

Download: (~1.1 MB)

Video: (~2.6 MB)

Improve PollingDuplex reliability with Silverlight 3.0

2009-04-07T23:43:23+01:00 by Andrea Boschin

The need to consume a continuous flow of data from a RIA application has two tipical solution. The first one involve the use of a Socket channel and probably is the most realiable when there is full acces to the ports  exposed by a server to the network. But this is rarely an available solution. Firewall, proxies and other kind of network apparates often restrict the access to a very tiny set of ports, possibly only to the http port 80. In this case the last solution available is to continuous poll the server and pulling data at every timeout.

timetableThis tecnique is slightly inefficient and prone to overload the server. If the need is to have very fast updates you have to rely on very short timeout but this may cause the server to fail under a great number of clients. On the other side having a long timeout may lost precision on the updates and give bad informations to users.

Silverlight 2.0 introduced a new mode to consume WCF services that allow to have the better of the server polling, using the only available http port, without short timeouts. With long timeouts we may also have updates very quickly thanks to a smart polling tecnique. Polling a server usually cause the client to be connected to the server only for few milliseconds and between connections there is a long disconnected period (the timeout). With Silverlight 2.0 PollingDuplex, channels can be connected during the whole timeout period and disconnect only for the short time needed to refresh the connection or notify the client of available updates. To do this "magic" the PollingDuplex simply open a connection to the server and wait for this connection to expire for a given period of time. If something happen on the server during this waiting the connection will be closed by the server itself and the client receive the notification with the related data.

Since its implementation many months ago this tecnique has been covered by many articles on the Internet so we do not need to add some other words to them. Here we need instead to analyze the changes that Silverlight 3.0 have introduced in this implementation that grant the developer a more reliable and simple usage of the PollingDuplex channels. To explore this new model I introduce a simple but effective application that monitors bus traffic.

Setup PollingDuplexHttpBinding

With Silverlight 2.0 setting up a duplex channel was a task hard and prone to errors. Due to the missing of an auto generated proxy the creation of a duplex connection and the control of its lifetime involve the direct usage of WCF channels and the management of at least a thread to monitor the polling channel. A detailed article explaining this tecnique may be found .

The main activity for the Silverlight team on this feature was to simplify the task of establishing the connection. With Silverlight 3.0 Visual Studio now support the generation of proxy class directly from the IDE in a similar way what we do with normal WCF services.

After the creation of the proxy - where it is possible to set properties like the type to be used for collections and dictionaries - the IDE generates a client class that can be simply used to establish the connection and receive updates. Here is a snippet of code, from the downloadable source, that show how to complete this task:

   1: /// <summary>
   2: /// Starts this instance.
   3: /// </summary>
   4: public static void Start()
   5: {
   6:     CustomBinding binding = new CustomBinding(
   7:         new PollingDuplexBindingElement(),
   8:         new BinaryMessageEncodingBindingElement(),
   9:         new HttpTransportBindingElement());
  10:  
  11:     TimeServiceClient client = new TimeServiceClient(binding, GetEndPoint());
  12:     
  13:     client.UpdateReceived += new EventHandler<UpdateReceivedEventArgs>(client_UpdateReceived);
  14:     client.RegisterAsync();
  15: }

In this few lines of code the TimeServiceClient is created. This client has to be setup with a binding compatible with the binding exposed by the server. In this case we need a custom binding using the new binary XML through the BinaryMessageEncodingBindingElement. The other element used establish a PollingDuplex channel over an http transport.

The other lines of code attach an Update event (exposed by the CallbackContract interface) and then calls the Register method (exposed by the ServiceContract) to start the polling. When this method completes - and we have an event available to check about his completion - the channel is up and running. Every time an update is available the UpdateReceived event will be raised and we may update the interface according to this data.

On the client the work is done. There is no need to have threads and all the received updates are always marshaled to the UI thread context so it is possible to update directly the User Interface.

In this sample we will simulate a timetable that show incoming races on a bus stop. When a bus is arriving to the stop the server will update the connected clients that will shows the times on the Silverlight scene. In this scenario we need to have very quicly updates and to minimize the traffic and the server work.

Creating a WCF Polling Server

The server side of the polling channel is slightly more complicated. This is not due to complexity of the PollingDuplex channel, but due to the needs to maintain trace of the registered clients and to notify them every time an update is available.

A polling duplex channel is made of two contracts instead of the usual one of normal WCF services. The first contract represent the normal ServiceContract that expose the ServiceOperations available to be called. On the other way we need to have a CallbackContract that say how a server can call on a client when an update is available and needs to notify it.

When a client connect to the service, using the Register method, the service itself will ask the OperationContext about the CallbackContract available over the client. An instance of the contract, returned by the GetCallbackChannel<T>() method will be retained by the service and used whenever it need to notify clients. Mantaining this instances needs to manage a shared collection of items and syncronize access to the elements using a lock statement. This is required because when a service instance has been created it is shared by all the calls that the service handles. So in a multi threaded environment like the context of a running webserver we have to keep in mind that the concurrency on the client callbacks contracts can affect the performances of out system.

In the sample attached to this article this responsability is of the TimeRunner class that handles the clinet collection and manage locks:

   1: /// <summary>
   2: /// Registers the specified client.
   3: /// </summary>
   4: /// <param name="client">The client.</param>
   5: public static void Register(ITimeServiceClient client)
   6: {
   7:     lock (lockObj)
   8:     {
   9:         TimeClient timeClient = new TimeClient(client);
  10:         timeClient.Fault += new EventHandler(timeClient_Fault);
  11:         TimeRunner.Clients.Add(timeClient);
  12:  
  13:         // ... omissis ...
  14:     }
  15: }

Another responsibility we have on the server side is the management of the client Fault states. A fault is the condition we may encounter when trying to send and update to a callback we get an exception because the client has been closed. There is no way to be notified about client disconnection so the only way to get rid of this problem is catching exceptions during an update. For each client connected to the service it will create an instance of a TimeClient class. This class checks the fault states when a client is updating and raise an event that signal to the TimeRunner the needs of remove the TimeClient instance from the collection:

   1: /// <summary>
   2: /// Handles the Fault event of the timeClient control.
   3: /// </summary>
   4: /// <param name="sender">The source of the event.</param>
   5: /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
   6: private static void timeClient_Fault(object sender, EventArgs e)
   7: {
   8:     lock (lockObj)
   9:     {
  10:         TimeClient timeClient = (TimeClient)sender;
  11:         TimeRunner.Clients.Remove(timeClient);
  12:         timeClient.Dispose();
  13:     }
  14: }

Let doing something...

Now that the service communication layer has been prepared to handle multiple incoming requests and updates we need to proceed start doing something in the service. While a normal WCF service simply handle calls from the web to do its work syncronous with the client, a Duplex service has to act as a worker thread that get notifications about the monitored resource and then contact the clients to send updates. The worker thread can wait for a database table to be updated, or can wait for other incoming event. In my sample I use a FileSystemWatcher to monitor changes to an xml file. The timetable.xml file contains sample data about races passing in a bus stop. I imagined that a windows service is collecting informations about the bus running ina town and when it have updates simply write to a xml file. This writing is catched by the FileSystemWatcher and notify the WCF duplex service thread. The notification received by the service cause the timetable to be loaded and a diffgram is send to the connected clients.

   1: /// <summary>
   2: /// Handles the Changed event of the Watcher control.
   3: /// </summary>
   4: /// <param name="sender">The source of the event.</param>
   5: /// <param name="e">The <see cref="System.IO.FileSystemEventArgs"/> instance containing the event data.</param>
   6: private static void Watcher_Changed(object sender, FileSystemEventArgs e)
   7: {
   8:     RacesTable table = LoadRaces();
   9:  
  10:     RaceUpdate update = new RaceUpdate
  11:     {
  12:         AddedOrModified = (from upd in table.Races
  13:                            where !TimeRunner.CurrentTable.Races.Contains(upd)
  14:                            select upd).ToArray(),
  15:         Deleted = (from old in TimeRunner.CurrentTable.Races
  16:                    where !table.Races.Select(rc => rc.UniqueID).Contains(old.UniqueID)
  17:                    select old).ToArray()
  18:     };
  19:  
  20:     lock (lockObj)
  21:     {
  22:         for(int i=0; i<TimeRunner.Clients.Count; i++)
  23:         {
  24:             TimeClient client = TimeRunner.Clients[i];
  25:             if (!client.IsSending) client.Send(update);
  26:         }
  27:     }
  28:  
  29:     TimeRunner.CurrentTable = table;
  30: }

The diffgram is calculated using an image of the timetable in memory that contains the latest version of the file. The new file and the old image is compared using linq and the diffgram is created with Added, Modified and Deleted items. The client that receive this update simply apply this changes tho his own copy of the timetable. The only exception to this flow happen when a client connect . In this case it get the complete content of the timetable from the memory of the service.

Hosting service and serving policies

A duplex service may be hosted by Internet Information Service, by a windows service or by a simple console application. In this example I choose to use a console application to maintain the source code simple. While using the IIS as host allow to serve clientaccesspolicy.xml files in a simple way, using a windows process needs to implements some tricks to serve this file as we did if we have a webserver. To do this I've implemented an endpoint using the webHttpBinding and return the xml file when it is requested. For more detail on this tecnique please read this .

Now that the sample has been described you may run it by yourself. Firts of all you need to run the service application and then starts the web application containing the Silverlight xap.

Download: Elite.Silverlight3.Polling.zip (1,4 MB)
Categories:   Networking
Actions:   E-mail | del.icio.us | Permalink | Comments (17) | Comment RSSRSS comment feed

A proxy class to tunnel Socket channels

2009-04-01T23:00:00+01:00 by Andrea Boschin

One of the requests I found, following the Silverlight forums, is the capability to connect a Socket to an arbitrary port out of the restricted range where Silverlight is allowed to work. Since the release 2.0, Silverlight is allowed to connect to the network using a Socket but has a limitation that forbid the access to ports out of the range from 4502 to 4534. Another requirements for the sockets to work is that the same service must expose a clientaccesspolicy.xml file on a well known port 943 stating the ports opened by the service.

This complicated context let the use of the Sockets difficult and limitated to custom services. The limit of 32 ports opened is fine if someone has to create a custom service giving realtime updates, but is frustrating if the need is to access a well know network service like DNS, Telnet and other. We have to know that some network protocols are impossible to be implemented with Silverlight because of them nature. Thinking about FTP the duplex nature of this service, where server and client exchange their role (the client become server when receiving a file)  let this protocol impossible to be implemented in Silverlight where there is no way to listen to incoming connections. There is a number of other existing services, and often a number of existing custom services that rely on ports out of the 4502-4534 range and that we would like to consume without changing the code because often they are already published to other systems.

In this article I will explain a simple project I've implemented to let some services to be "tunneled" moving their original port to another port in the range allowed to Silverlight. This service that is freely downloadable at the end of the post, also implements a channel on the port 943 to allow Silverlight to get the client access policies before to connect to the tunneled ports.

The system Architecture

Before showing some snippets of code I will try to explain how my solution works. I will go through the architecture showing the components and the reason of my choice. The first concept you may know about implementing Sockets is that when you are listening on a port you are waiting for accepting clients and when a client connect you need to start a thread that take the accepted client and manage it separately from the main listening socket. This behavioh allow you to manage multiple incoming clients giving each connection in charge to a separate thread and leaving the port free to return a the listening task. Another requirement we have developing the solution for Silverlight is to have two servers listening, one for the policy distribution and the other on the proxy service that forward traffic to the required port.

To solve this problem I've created a base class ThreadedObject that implements the base behavior of every subsystem. From this class I've inherited three types that manage the different parts of the problem.

classes

The ThreadedObject class is in charge of managing the lifetime of the thread. It is a IDisposable class so it is created with an using construct and this cause the closing of the thread when the class goes out of scope. The trick is the usage of a ManualResetEvent exposed to the subclasses. When this event will be set the thread has to exit gracefully.

The SocketProxy class

This class have in charge the task to listen for incoming connections on both the policy port 943 and the proxy channel that we will expose on the port 4530. I've created this class thinking about a developer that needs to embed a listening proxy in a Windows service. It is a simple class that request a few parameters in input and when started run a thread that listen. As you may know the parameters tells the host and the ports where to listen and forward connections. In my solution this parameters are read from the app.config file. The constructor wants also the path of a policy file. Here is the main thread procedure of the class:

   1: /// <summary>
   2: /// Listen the thread.
   3: /// </summary>
   4: /// <param name="state">The state.</param>
   5: protected override void ThreadProc()
   6: {
   7:     IPHostEntry hostEntry = Dns.GetHostEntry(this.ListenHost);
   8:     IPAddress ipAddress = hostEntry.AddressList.Where(entry => entry.AddressFamily == AddressFamily.InterNetwork).FirstOrDefault();
   9:  
  10:     if (ipAddress != null)
  11:     {
  12:         this.PolicyListener = new TcpListener(ipAddress, 943);
  13:         this.PolicyListener.Start();
  14:         this.ProxyListener = new TcpListener(ipAddress, this.ListenPort);
  15:         this.ProxyListener.Start();
  16:  
  17:         while (WaitHandle.WaitTimeout == WaitHandle.WaitAny(this.ExitHandles, 10))
  18:         {
  19:             if (this.PolicyListener.Pending())
  20:             {
  21:                 PolicyClient policyClient =
  22:                     new PolicyClient(this.PolicyListener.AcceptTcpClient(), this.PolicyFile);
  23:                 policyClient.Start();
  24:  
  25:             }
  26:             else if (this.ProxyListener.Pending())
  27:             {
  28:                 ProxyClient proxyClient = 
  29:                     new ProxyClient(this.ProxyListener.AcceptTcpClient(), this.TargetHost, this.TargetPort);
  30:                 proxyClient.Start();
  31:             }
  32:         }
  33:     }
  34:     else
  35:         throw new ApplicationException(Resources.CannotResolveAddress);
  36: }

The class starts two instances of TcpListener and then poll the Pending() method to check when there is waiting clients to accept. When a client is ready it starts an instance of the managing type.

The PolicyClient

This class implements a manager for the clients requesting the policies. It will be started by the SocketProxy class when a client ask for a connection. The class operate in two steps: first of all it wait for the client to send the policy request string then it sends the policy file and finally close the connection:

   1: /// <summary>
   2: /// Threads the proc.
   3: /// </summary>
   4: protected override void ThreadProc()
   5: {
   6:     try
   7:     {
   8:         while (WaitHandle.WaitTimeout == WaitHandle.WaitAny(this.ExitHandles, 10) &&
   9:             this.Client.Available == 0) ;
  10:  
  11:         ReadAndSend();
  12:     }
  13:     finally
  14:     {
  15:         this.Client.Close();
  16:     }
  17: }
  18:  
  19: /// <summary>
  20: /// Validates the and send.
  21: /// </summary>
  22: /// <returns></returns>
  23: private void ReadAndSend()
  24: {
  25:     NetworkStream stream = this.Client.GetStream();
  26:  
  27:     byte[] data = new byte[PolicyRequestString.Length];
  28:     stream.Read(data, 0, data.Length);
  29:  
  30:     string readString = Encoding.UTF8.GetString(data);
  31:  
  32:     if (readString == PolicyRequestString)
  33:     {
  34:         stream.Write(this.PolicyFile, 0, this.PolicyFile.Length);
  35:         stream.Flush();
  36:     }
  37: }

The class request in the constructor a byte array of the policy file to send. This buffer is loaded by the SocketProxy class and then decoded to a byte array and passed to all the instances.

The ProxyClient

This is the most critical class that have in charge the clients when tunneling the traffic in both the directions. It will have two clients; the silverlight part and the tunneled service part. It simply wait for traffic from each client and forward it to the other. The operation of tunneling the data is the critical part. I read the data from a channel in 1024 bytes chunks and write the same bytes on the other client. I think this part has to be tested on various services and tuned finding the best strategy. The current implementation may fail when both parts of the channel is data intensive because reading data from a channel stops reading data from the other.

   1: /// <summary>
   2: /// Threads the proc.
   3: /// </summary>
   4: protected override void ThreadProc()
   5: {
   6:     try
   7:     {
   8:         while (WaitHandle.WaitTimeout == WaitHandle.WaitAny(this.ExitHandles, 10) &&
   9:             this.Client.Available == 0) ;
  10:  
  11:         ReadAndSend();
  12:     }
  13:     finally
  14:     {
  15:         this.Client.Close();
  16:     }
  17: }
  18:  
  19: /// <summary>
  20: /// Validates the and send.
  21: /// </summary>
  22: /// <returns></returns>
  23: private void ReadAndSend()
  24: {
  25:     NetworkStream stream = this.Client.GetStream();
  26:  
  27:     byte[] data = new byte[PolicyRequestString.Length];
  28:     stream.Read(data, 0, data.Length);
  29:  
  30:     string readString = Encoding.UTF8.GetString(data);
  31:  
  32:     if (readString == PolicyRequestString)
  33:     {
  34:         stream.Write(this.PolicyFile, 0, this.PolicyFile.Length);
  35:         stream.Flush();
  36:     }
  37: }

Testing the application

To test the class I've selected a service from the canonical ports exposed by a system.  Finally I've selected the daytime port 13. It is a service that on Windows has to be installed under the Simple TCP services and then started by the Services applet. The choice of this simple and slightly unuseful ports is only to give a very simple example that show how to expose a port that is really out of the Silverlight range. My simple application has a button and a TextBlock. When the Button is clicked a Socket connection will be made to appthe daytime service and the returned system time will be displayed in the TextBlock.

The server part is configured to tunnel connection incoming on port 4530 to the system dtaytime port and to serve a policy file from the file system.

I'm thinking to write a more powerful sample on this code. Opening ports to the silverlight applications may open a wide range of solutions limited only by your creativity and probably by your it manager. When exposing a port on the internet you have to concern about security issues. Every opened port to the network is a potential security disclosure but the security must be implemented in the protocol you are exposing. Also you have to know that exposing a well-know port may give an opportunity to use a well know bug to enter your system.

Download: Elite.Silverlight.SocketProxy.zip (1,1 MB)

Where is Silverlight Mobile?

2009-03-31T14:48:18+01:00 by Andrea Boschin

This question has been answered many times since presented his beta during the Mix 2007. Many of you are waiting from about 2 years to have a first build available to start working and I think that many of you thinked that this project is dead due to the long time passed from its presentation.

Today has published a post about this argument that resume the history of this platform and switch on some light about the future of Silverlight Mobile. The last sentence of his post is the more interesting:

This makes Silverlight mobile being released in line with the Windows 7 mobile platform.  I am hoping we see a beta/CTP around the Visual Studio 2010 release.

Hoping that Bart is right on the supposed timing I leave you to the reading of his interesting post.

Link: Silverlight 3 - Where is Silverlight Mobile?

Categories:   Mobile
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed

C64 Emulator Video

2009-03-23T09:37:03+01:00 by Andrea Boschin

Pete Brown has written an interesting C64 emulator that show what Silverlight 3.0 can do. The C64 Emulator he shows during the MIX09 is a generated MediaStreamSource continuously updated by the emulator runtime. This grant a very amazing fluid result. In this article a more .

Link:

Categories:   Demo
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed

Silverlight 3.0: Tile Effect with a Pixel Shader

2009-03-22T23:20:09+01:00 by Andrea Boschin

Listening what has been asked in the Silverlight forums I've found someone searching for a TileBrush. This kind of brush, in WPF can be used to create a Tile of repeated elements. Unfortunately the TileBrush exists in Silverlight but is only a placeholder ready for future development and for WPF compatibility.

In a thread I found to work around this missing thing. He suggested to create a Pixel Shader with Silverlight 3.0 to enable tiling. So I've decided to start studing Pixel Shaders to try create an Effect that may be used for this purpose. In this brief article I will get into this argument and explain how Pixel Shaders works and how they may be used in Silverlight 3.0.

What is a Pixel Shader

When the GPU (Graphic Processing Unit) are rendering a scene from a 3D model to its bidimensional representation it works in 3 steps. Starting from the 3D Model it go through Vertex Shaders, Pixel Shader and finally to the Frame Buffer. The first step called of "Vertex Shaders" involve the transformation of the 3D space and is out out the scope of this article. We now concentrate to the second step where Pixel Shaders start working.

To be most simpler, a Pixel Shader is a small program that transform an image pixel-by-pixel to another image that will be trasmitted to the Frame Buffer for the display. It is made of a function that will be called to transform every single pixel. The shader is written in an high level, c-like language called HLSL () and may take advantage of many primitive function to easily manipulate the pixels and create effects like bump mapping, brightness, distortion, etc...

Here is the code of a simple Pixel Shader:

   1: // .. omissis ..
   2:  
   3: float4 main(float2 uv : TEXCOORD) : COLOR
   4: {
   5:     return tex2D( implicitInputSampler, uv );
   6: }
   7:  
   8: // .. omissis ..

This code simply does nothing. The input value is used to return the color of the pixels so the Frame Buffer will receive the original picture. In this short chunk of code we may use subroutines, math functions and a type system optimized for working with images.

Here is another example:

   1: float4 main(float2 uv : TEXCOORD) : COLOR
   2: {
   3:    return tex2D( implicitInputSampler, 1 - uv );
   4: }

This shader do a reverse of the original image putting the top-left pixel on the bottom-right side and so-on. Using shader there are 32 registers where we can load some information coming from the software we are developing. "implicitInputSamples" in my example contains the input image to be transformed. Using this registers it is possible to parametrize a shader.

Working with shaders is not simple. Fortunately there is Shazzam, a wonderful click once WPF application you can download and that helps in developing the Pixel Shaders. This tool has been developed for WPF but it is useful also for Silverlight because it support the same version of Pixel Shaders 2.0 than WPF.

I think this is sufficent to show how powerful may be the Pixel Shaders. If you need some more samples please watch this . In the same page you may find a big number of shaders. I will stop here with the explanation because the argument is too extensive for the scope of this post. For a more detailed explanation please refer to .

Create a Tiling Pixel Shader

After understanding how a Pixel Shader works, we can now try to create our tiling shader as first step. While we get the pixels in our shader (a value from 0 to 1) there is a simple operation we can do to replicate the original image horizontally and vertically. Here is the operation:

x * tiles % 1

This simple operation will be repeated for x and y coordinates and get an argument "tiles" that define how many tiles we need to show. This value may be different for vertical or horizontal direction. We can try to write the shader now:

   1: //
   2: // Created by A.Boschin: andrea@boschin.it
   3: // site: http://www.silverlightplayground.org
   4: // blog: http://blog.boschin.it
   5: //
   6:  
   7: // vertical count of tiles
   8: float verticalTileCount : register(C1);
   9:  
  10: // horizontal count of tiles
  11: float horizontalTileCount : register(C2);
  12:  
  13: // inputBrush
  14: sampler2D implicitInputSampler : register(S0);
  15:  
  16: // Pixel Shader
  17:  
  18: float4 main(float2 uv : TEXCOORD) : COLOR
  19: {
  20:     float2 newUv = float2(uv.x * horizontalTileCount % 1, uv.y * verticalTileCount % 1);
  21:    
  22:     return tex2D( implicitInputSampler, newUv );
  23: }

As I have anticipated the shader get two arguments.

verticalTileCount : vertical number of tiles

horizontalTileCount : horizontal number of tiles

implicitInputSampler : the input image

If you are using Shazzam it will creates a class and a user interface to test the shaders. Using the sliders you will see the tiling appear. The numbers from 0 to 1 will transform the image to a biggest version, but the numbers bigger the 1 will transform the image.

Make our shader works in Silverlight

After created and tested the shader it is now time to use it in Silverlight 3.0. The first thing to do is compile the shader. Shazzam compile a shader in a .ps file and this is the file we have to copy in our solution. Next it is required to set the .ps file with a "Content" build action.

We have now to create an Effect that we may apply to every class derivated by UIElement. The effect can be applied to images or to elements like Buttons and every other element that supports the Effects. To use a Pixel Shader we have to create a class deriving from ShaderEffect. This class contains many functions and all the logic needed to incapsulate a compiled Pixel Shader and make it work.

The Effect class will have two dependency property wrapping vertical and horizontal. Using a Dependency Property will enable us to do DataBinding on this properties or to enable wonderful animated effects. Next we have to create a Sampler property. This is the property that encapsulate the input brush. Here is the code of the TileEffect:

   1: public class TileEffect : ShaderEffect
   2: {
   3:     public static DependencyProperty InputProperty =
   4:         ShaderEffect.RegisterPixelShaderSamplerProperty("Input", typeof(TileEffect), 0);
   5:  
   6:     public static DependencyProperty VerticalTileCountProperty =
   7:         DependencyProperty.Register(
   8:             "VerticalTileCount",
   9:             typeof(double),
  10:             typeof(TileEffect),
  11:             new PropertyMetadata(1.0, PixelShaderConstantCallback(1)));
  12:  
  13:     public static DependencyProperty HorizontalTileCountProperty =
  14:         DependencyProperty.Register(
  15:             "HorizontalTileCount",
  16:             typeof(double),
  17:             typeof(TileEffect),
  18:             new PropertyMetadata(1.0, PixelShaderConstantCallback(2)));
  19:  
  20:     public TileEffect()
  21:     {
  22:         // Note: for your project you must decide how to use the generated ShaderEffect class (Choose A or B below).
  23:         // B: Uncomment the following two lines - which load the *.ps file
  24:         Uri ps = new Uri("tile.ps", UriKind.RelativeOrAbsolute);
  25:         PixelShader = new PixelShader() { UriSource = ps };
  26:  
  27:         // Must initialize each DependencyProperty that's affliated with a shader register
  28:         // Ensures the shader initializes to the proper default value.
  29:         this.UpdateShaderValue(InputProperty);
  30:         this.UpdateShaderValue(VerticalTileCountProperty);
  31:         this.UpdateShaderValue(HorizontalTileCountProperty);
  32:     }
  33:  
  34:     /// <summary>
  35:     /// Gets or sets the input.
  36:     /// </summary>
  37:     /// <value>The input.</value>
  38:     public virtual System.Windows.Media.Brush Input
  39:     {
  40:         get
  41:         {
  42:             return ((System.Windows.Media.Brush)(GetValue(InputProperty)));
  43:         }
  44:         set
  45:         {
  46:             SetValue(InputProperty, value);
  47:         }
  48:     }
  49:  
  50:     /// <summary>
  51:     /// Gets or sets the vertical tile count.
  52:     /// </summary>
  53:     /// <value>The vertical tile count.</value>
  54:     public virtual double VerticalTileCount
  55:     {
  56:         get
  57:         {
  58:             return ((double)(GetValue(VerticalTileCountProperty)));
  59:         }
  60:         set
  61:         {
  62:             SetValue(VerticalTileCountProperty, value);
  63:         }
  64:     }
  65:  
  66:     /// <summary>
  67:     /// Gets or sets the horizontal tile count.
  68:     /// </summary>
  69:     /// <value>The horizontal tile count.</value>
  70:     public virtual double HorizontalTileCount
  71:     {
  72:         get
  73:         {
  74:             return ((double)(GetValue(HorizontalTileCountProperty)));
  75:         }
  76:         set
  77:         {
  78:             SetValue(HorizontalTileCountProperty, value);
  79:         }
  80:     }
  81: }

All the work is done in the constructor where we create a reference to the .ps file in the project and an istance of the PixelShader class. Then we have to initialize the properties to let the runtime read the values. This is all the work we need. The TileEffect now is ready to be embedded in Silverlight.

Using the TileEffect

If you had a try on how to use the DropShadowEffect you know exactly how to use the TileEffect. The only thing we have to do is to declase the namespace "local" before get access to the class. Then you add the effect in the markup code and it works:

   1: <UserControl x:Class="Elite.Silverlight3.PixelShaders.Silverlight.MainPage"
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
   4:     xmlns:local="clr-namespace:Elite.Silverlight3.PixelShaders.Silverlight"
   5:     Width="Auto" Height="Auto" Background="#FF000000">
   6:     <Grid x:Name="LayoutRoot" Background="#FF000000" HorizontalAlignment="Center" VerticalAlignment="Center">
   7:         <Image Grid.Column="0" Grid.Row="0" Source="parachute.jpg" Width="640" Height="426">
   8:             <Image.Effect>
   9:                 <local:TileEffect x:Name="tile" HorizontalTileCount="2" VerticalTileCount="2" />
  10:             </Image.Effect>
  11:         </Image>
  12:     </Grid>
  13: </UserControl>

The attached sample do something more. The effect properties has been binded to two sliders so moving the slider we can change the vertical and horizontal values of the effect.

Here is a screenshot of the working application:

tiles

Attached you may found the project and a small video showing the effect working.

Download: Elite.Silverlight3.PixelShaders.zip (~2.2 MB)

Video: TilingPixelShader.wmv (~714 KB)

Categories:   Effects
Actions:   E-mail | del.icio.us | Permalink | Comments (14) | Comment RSSRSS comment feed

Installing Silverlight 3.0 side-by-side with Silverlight 2.0

2009-03-22T08:35:21+01:00 by Andrea Boschin

A useful tip has been published by , about how to install Silverlight 2.0 and 3.0 on the same machine an continue working with both. You have to take note that the Silverlight 3.0 runtime will override the Silverlight 2.0 runtime but due to the big work in backward compatibility this would not be a big problem.

The tip require a batch script to switch from a version to another of the Visual Studio Tools. Included in the tip there is also a way to change the projects to work with both versions of the tools.

Link:

Categories:   TIPS
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed

MIX09 Keynote Demo Available

2009-03-22T08:21:49+01:00 by Andrea Boschin

The source code of the demo showed by Scott Guthrie during the Keynote of the MIX 2009 last week has been made available by Henry Hahn. It is a very amazing demonstration on how it is possible to do with the new features of Silverlight 3.0.

The demo derive from a similar project crated the last year for MIX 08 about WPF.

ripple

| | Download Project

Categories:   Demo | Animations | Effects
Actions:   E-mail | del.icio.us | Permalink | Comments (1) | Comment RSSRSS comment feed

Links to Silverlight 3.0 resources

2009-03-19T09:26:07+01:00 by Andrea Boschin

The release of the Silverlight 3.0 beta 1 has triggered a long series of posts on new features: here is a little serie of links to visit:

Categories:  
Actions:   E-mail | del.icio.us | Permalink | Comments (3) | Comment RSSRSS comment feed

Silverlight Toolkit per SL3 has been released

2009-03-19T08:59:49+01:00 by Andrea Boschin

After the annoncements of yesterday a new release of the Silverlight Toolkit has been deployed.

The March 2009 Toolkit has been released in two downloads: a Silverlight 2 and a Silverlight 3 Beta targeting installer.

Here is in some new feature listed

  • New! Charting – AreaSeries
  • New! LayoutTrasnformer
  • New! TimeUpDown
  • New! TimePicker
  • New! ListTimePickerPoup & RangeTimePickerPopup
  • New! Accordion
  • New! DomainUpdown
  • New! 2 new themes: Bubble Crème and Twilight Blue
Categories:  
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed

Silverlight 3.0: Out of browser experience

2009-03-18T19:00:00+01:00 by Andrea Boschin

Read also updates targeting Silverlight 3.0 RTW
http://www.silverlightplayground.org/post/2009/07/10/Whats-new-about-Out-Of-Browser-in-Silverlight-30-RTW.aspx 

Many times, when using a Silverlight application, I thinked about how cool would be to detach the application from the browser and use it directly from my desktop. Some Silverlight application are really lightweighted and can easily used on many platforms without to have to install it in the computer; the only thing needed is the Silverlight runtime.

This scenario I've described in a few words may open the way to a new big set of applications. Think as an example at an application that may be used both online and offline checking for network connectivity and synchronizing the modification of the local storage to a global online repository. You may detach multiple instances of the application in many computers, the office workstation, the home PC, your mini notebook and have them synchronized each other when you apply some changes. This may be a real occasionally connected application.

Out of browser experience and Silverlight 3.0

ctxmenu The biggest feature of the new Silverlight 3.0, called Out of browser experience, OOB for the friends, let you start creating application that can easily detached and used from a simple host without the need of a browser instance. The action of detaching the application is really simple, very fast and do not need any kind of installer. You have simply to right click the running application and if it is configured correctly you will find an "Install ... onto this computer..." item. The only question you need to answer is where you want silverlight let create the icon, on the Desktop or in the Start menu (or both) and then your OOB will be started and ready to be used.

The use of this kind of experience need open some problem we will analize in the next paragraphs, as usual using a small project as a guide. I've build a very tiny ToDoList application in Silverlight to let manage some simple todo, with a title a description and an optional due date. The application is ready to detect network changes and to synchronize contents using a WCF service, but this part is not implemented because is out of the scope of this article.

Configuring the Out Of Browser Experience

The first problem we have to address after we have completed our development, is how to configure it to let the user detach the application to be able to run it online and offline without a browser. This is a quite simply task. In the silverlight project you have to find the AppManifest.xml file under the Properties folder and uncomment a special section. Obviously you may also customize some properties:

   1: <Deployment.ApplicationIdentity>
   2:   <ApplicationIdentity ShortName="ToDoList"
   3:                        Title="Silverlight ToDoList">
   4:     <ApplicationIdentity.Blurb>
   5:       Manage offline your tasks
   6:     </ApplicationIdentity.Blurb>
   7:   </ApplicationIdentity>
   8: </Deployment.ApplicationIdentity>

The properties you can customize are the ShortName that will appear on the menu item, the title and the description (blurb) that will be displayed in the installation window. You may also add an optional <ApplicationIdentity.Icons> section. This let you add some icons in png format to be displayed on the desktop or start menu.

install

The installation window let you decide how to install  the application you are detaching. You may choice to add some icons, one on the destop and one on the Start menu.

This is the only action you need to perform. If you click yes the files required to run the application will be copied into a folder in AppData and the icons wil be created as shortcut to the sllauncher.exe into the Silverlight 3.0 install location.

The folder where the application files will be copied is C:\User\...\AppData\LocalLow\Microsoft\Silverlight\Offline.

After installing the OOB application you may run it again double clicking on the icons. You may also uninstall it simply right clicking on the running instance and selecting "Remove this application..." from the context menu.

The installation process may be triggered programmatically using the Detach() method of the Application class. This the the developer to add a button that indicate to the user that the application may be detached. The Application.RunningOffline property let the developer know if the Application is already detached. Using this property we may show the installation instructions when the application is in the browser and the remote them when installed.

If you imagine to have a "detach" button you can write this code:

   1: this.detach.Visibility = 
   2:     Application.Current.RunningOffline ? Visibility.Collapsed : Visibility.Visible;
   3:  
   4: this.detach.Click += (sender, e) => Application.Current.Detach();

We may get information about the installation (detaching) or disinstallation of the application handling the event ExecutionStateChanged and reading the ExecutionState property in the Application.Current instance. This property let us know that the state of the application is:

  • Detached - The application has successful detached
  • DetachedUpdatesAvailable - see the paragraph (Updating the application)
  • DetachFailed - The detach is failed
  • Detaching - The detach is in progress
  • RunningOnline - The application is into the browser

Store local data: Isolated Storage

Running an Out of browser application imply to have a location where to store some data when the application is Offline. Unfortunately there is no way to access the local filesystem, also if the application is Detached by the user and also there is not any way to consume some kind of database (e.g. a Sql Server Mobile file).

The only place you can use to persist information is the local IsolatedStorage. The example application attached to this article use the IsolatedStorage to persist a simple XML file containing the Tasks and the actions the user apply to them. This XML is loaded at the application startup and saved to the storage every time the user modify the data. To handle the synchronization of the modification to the online store the XML contains a status and version for each Task. This information may be used by the WCF Service to manage the updating of the online store.

Detecting network changes

After our OOB application is ready and works against the isolated storage we needs to detect when the user go online to trigger the syncronization with the online storage. The sncronization is made of two parts: we need to update the online store with the updates applied locally and the we needs to download locally the updates applied by other instances of the OOB application.

Detecting the network changes is sligthly simple. We may use two classes called NetworkChange and NetworkInterface. The first class expose and event that let us known when the network status has changed from online to offline and viceversa:

   1: NetworkChange.NetworkAddressChanged +=
   2:     new NetworkAddressChangedEventHandler(NetworkChange_NetworkAddressChanged);
   3:  
   4: // ... omissis ...
   5:  
   6: private void NetworkChange_NetworkAddressChanged(object sender, EventArgs e)
   7: {    
   8:     if (NetworkInterface.GetIsNetworkAvailable() && this.NeedUpdate)
   9:     {
  10:  
  11:     }
  12: }

The events triggered by the NetworkChange class do not contains any informations about the connection is up or down. This event let us to know only that something has changed. Also we have to take note that the event will be triggered multiple times depending how many adapters are connected to the host computer so we have to handle this event accurately.

To detect if we are are running online or offline we may use the GetIsNetworkAvailable() method. This method returns true if this ia any connected network else it returns false. In the application we check also the NeedUpdate property to avoid that the update process will be triggered too many times if the network connect or disconnect many times due to network instability. In this application NeedUpdate returns true only if at least 1 hour has passed after the last successful update.

Updating the application

When an application is running online every time we connect to the host site we get the latest version of the application. The silverlight plugin handles the updates of the xap downloading the file and discarting the cached version. When an application has ben taken out of browser we needs to have this check to run sometimes because we want our applicatio remain up to date.

The Silverlight 3.0 OOB application run this check every time the application starts on the host computer. If the network is available and an update has been detected the new xap will be downloaded and then the running application will be notified of the available update. It is in charge of the developer to decide to show to the user that the application has been updated. However when the application is closed and restarted the update will be applied. Here is the code to get the notification about updates:

   1: Application.Current.ExecutionStateChanged += 
   2:     new EventHandler(Current_ExecutionStateChanged);
   3:  
   4: // ... omissis ...
   5:  
   6: void Current_ExecutionStateChanged(object sender, EventArgs e)
   7: {
   8:     if (Application.Current.ExecutionState == ExecutionStates.DetachedUpdatesAvailable)
   9:         MessageBox.Show("Updates have been downloaded. Please restart the application to apply this updates.");
  10: }

There is no way to break the update process. When the application detect an update it try to download the new application and updates itself. I something fail (e.g. the network is disconnected), the update process restarts the next time the application run.

Running the sample

Attached to this article you may found a Visual Studio 2008 project that shows a real application using the Out Of Browser Experience. To run this sample you need to have the Silverlight 3.0 installed and the Silverlight Tools for Visual Studio 2008 updated to the latest version. You have to know that after installing this updates the computer will be a full Silverlight 3.0 machine so if you have to develope something with Silverlight 2.0 it is better you not install anything.

I think the OOB experience will trigger many new applications. The simple ToDoList I've created is the evidence that unleashing your fantasy you may think about many applications of this tecnique. In the next month I hope many of you will stars publish your own sample.

Download code: (2.02 MB)

Demo Video: (3.5 MB)

Silverlight 3.0: Application Extensibility

2009-03-18T18:44:00+01:00 by Andrea Boschin

Sometimes working with silverlight you need to have a sort of service, always available for global tasks or  working in background notifing the main thread when something happen. I've found this scenario many times during my work, as an example when I needed to poll a service to get periodic updates, or in another case with a caching service. Every time I developed this services using a static class or an instance of a class exposed by the Application, but the main problem is to manage the lifecycle to run or stop the service freeing the allocated resources when needed.

With Silverlight 3.0 this kind of services has been covered by a new tool named Application Services. An application Service is simply a class that implements the IApplicationService interface. This interface require two methods to be implemented by the Application Service class:

   1: public interface IApplicationService
   2: {
   3:     void StartService(ApplicationServiceContext context);
   4:     void StopService();
   5: }

This methods will be called by the Silverlight runtime when the service need to start during Application initialization and a few moments before the runtime terminate when the browser is closing or the user is navigating away. In the StartService() method the Application Service may run some code to begin his work, initializing variables, running threads and so on. On the other side the same service may notify threads to exit when the StopService() method is called by the runtime.

An Application Service class has to be registered in a specific section of the app.xaml. The application markup file is an ideal place to register this kind of classes. It a global location accessible by all the pages and controls, and the service instances may be simply configured with attributes mapping the class properties. Here is a sample of code showing how to register a FeedPollingService available in the sample source code:

   1: <Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   2:              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
   3:              xmlns:local="clr-namespace:Elite.Silverlight3.AppExtensibility"
   4:              x:Class="Elite.Silverlight3.AppExtensibility.App">
   5:     <Application.Services>
   6:         <local:FeedPollingService x:Name="polling" 
   7:                                 FeedType="RSS20"
   8:                                 FeedUrl="http://blog.boschin.it/rss.aspx" 
   9:                                 Timeout="10000" />
  10:     </Application.Services>
  11: </Application>

First of all the "local" namespace is declared in the Application tag. The application service is registered in the <Application.Services> element. This element needs you specify a unique name for the service instance. This name may be used to reach the instance from every class in the application. The configured FeedPolllingService exposes a "Completed" event we need to handle to get notified of feed download:

   1: public Page()
   2: {
   3:     FeedPollingService service = Application.Current.Services["polling"] as FeedPollingService;
   4:     service.Completed += new EventHandler<CompletedEventArgs>(service_Completed);
   5:     InitializeComponent();
   6: }

This happen in the Page constructor. In the service_Compleded event handler we simply handle the incoming feed binding it to the user interface to show the content. My service contains a thread that poll a rss feed every configured timeout so in the completed event I need to marshal the thread context using the Dispatcher object.

   1: #region IApplicationService Members
   2:  
   3: private ManualResetEvent exitEvent = new ManualResetEvent(false);
   4:  
   5: public void StartService(ApplicationServiceContext context)
   6: {
   7:     ThreadStart start = new ThreadStart(Service_Thread);
   8:     Thread thread = new Thread(start);
   9:     thread.Start();
  10: }
  11:  
  12: public void StopService()
  13: {
  14:     exitEvent.Set();
  15: }
  16:  
  17: #endregion

The FeedPollingService implements the IApplicationContext interface. In the StartService method the service start a thread that do the recurrent polling to the feed. In the StopService method instead a ManualResetEvent is triggered to notify the thread procedure to exit gracefully.

The other part of the application is simply the use of syndication to deserialize the downloaded feed and the binding of the feed items to the interface. The attached source code is available to test the Application Services.

Download Code: (2,07 MB)

Demo Video: (676 KB)

Tags:  
Categories:   .NET Programming
Actions:   E-mail | del.icio.us | Permalink | Comments (1) | Comment RSSRSS comment feed