Silverlight & XAML Playground
about XAML and other Amenities

Hierarchical binding with Implicit Data Templates

2012-01-12T23:52:41+01:00 by codeblock

Implicit data templates are a new interesting feature of Silverlight 5.0. They are a new way to create templates that automatically applies to specific types. So, imagine you have a set of types defined, and you want to present a collection of them inside an ItemsControl, you can use an Implicit Template that apply to each one of the types you are binding. Automatically this template will be applied to the give type every time it appear in the collection.

As you can figure out if may become really useful to present every item in a different way. Let say you have an Event base class and two derived Alarm and Information. You can bind the ItemsControl to an ObservableCollection<Event> as usual. Then you specify a different template for each one of the derived types:

   1: <ItemsControl ItemsSource="{Binding Events}">
   2:     <ItemsControl.Resources>
   3:         <DataTemplate DataType="om:Alarm">
   4:             <TextBlock Text="{Binding Message}" Foreground="Red" />
   5:         </DataTemplate>
   6:         <DataTemplate DataType="om:Information">
   7:             <TextBlock Text="{Binding Message}" Foreground="Black" />
   8:         </DataTemplate>
   9:     </ItemsControl.Resources>
  10: </ItemsControl>

Running the example you will get Alarm instances written in Red and Information instances written in black. The example is trivial just because I'm pretty sure you already read about Implicit Data Templates. The interesting thing to observe in this example i that you put templates in a Resources Section. This section apply to each one of the instances created inside of the ItemsControl.

After thinking a lot about this detail I realized you can use Implict Templates to bind Hierarchical structures and present each node with a different aspect based on the type ot the node. So I've taken the most obvious hierarchical structure - the filesystem - and I created a WCF method on top of it:

   1: public class FileSystemService : IFileSystemService
   2: {
   3:     public const string Root = @"C:\";
   4:  
   5:     public IEnumerable<FileSystemItem> GetItems(string path)
   6:     {
   7:         List<FileSystemItem> items = new List<FileSystemItem>();
   8:  
   9:         DirectoryInfo directory = new DirectoryInfo(Root + path);
  10:  
  11:         foreach (var item in directory.GetDirectories())
  12:         {
  13:             try
  14:             {
  15:                 items.Add(new Folder
  16:                 {
  17:                     Name = item.Name,
  18:                     HasChildren = item.GetFiles().Count() + item.GetDirectories().Count() > 0
  19:                 });
  20:             }
  21:             catch(UnauthorizedAccessException)
  22:             { }
  23:         }
  24:  
  25:         foreach (var item in directory.GetFiles())
  26:         {
  27:             items.Add(new File
  28:             {
  29:                 Name = item.Name,
  30:                 Size = item.Length
  31:             });
  32:         }
  33:  
  34:         return items;
  35:     }
  36: }

Two words about this code. It is a method that accept a string representing the path to retrieve. The method simply points to the specified path and enumerates Folders and Files adding a few information specific to the type. Size for the file and HasChildren for the Folder.

After this, the service is ready so it's time to create the proxy on the Silverlight project and then start creating the front end. For the best result I used the MVVM pattern and create a page with its ViewModel then a ViewModel for each of the types returned by the service.

   1: public class FileViewModel : FileSystemItemViewModel<File>
   2: { }
   3:  
   4: public class FolderViewModel : FileSystemItemViewModel<Folder>
   5: { }

At the first sight it may seems you can use directly the types that comes from the service but usig a ViewModel is the best choice because I have to get commands from the nodes and I need to lazy load children items. So indise the MainPage view model I start the chain loading the first level to present in the hierarchy:

   1: public class MainPageViewModel : ViewModelBase
   2: {
   3:     public ObservableCollection<ViewModelBase> Items { get; set; }
   4:  
   5:     public MainPageViewModel()
   6:     {
   7:         this.Items = new ObservableCollection<ViewModelBase>();
   8:         this.Load();
   9:     }
  10:  
  11:     private void Load()
  12:     {
  13:         FileSystemServiceClient client = new FileSystemServiceClient();
  14:         client.GetItemsCompleted += new EventHandler<GetItemsCompletedEventArgs>(client_GetItemsCompleted);
  15:         client.GetItemsAsync(string.Empty);
  16:     }
  17:  
  18:     private void client_GetItemsCompleted(object sender, GetItemsCompletedEventArgs e)
  19:     {
  20:         this.Items.Clear();
  21:  
  22:         foreach (var item in e.Result)
  23:         {
  24:             if (item is File)
  25:                 this.Items.Add(new FileViewModel(item as File));
  26:             else if (item is Folder)
  27:                 this.Items.Add(new FolderViewModel(item as Folder, string.Empty));
  28:         }
  29:     }
  30: }

Since the File will not have any action in this example, but in an extended example it may trigger the download of the file. For the purpose of the article I will concentrate on the FolderViewModel. When the item is clicked I expect that the children is loaded and presented in the UI. So here is the code:

   1: public class FolderViewModel : FileSystemItemViewModel<Folder>
   2: {
   3:     public FolderViewModel(Folder folder, string path)
   4:         : base(folder)
   5:     {
   6:         this.Path = path + "/" + folder.Name;
   7:         this.Items = new ObservableCollection<ViewModelBase>();
   8:         this.ClickCommand = new RelayCommand(Click);
   9:     }
  10:  
  11:     private void Click()
  12:     {
  13:         if (this.Items.Count == 0)
  14:         {
  15:             FileSystemServiceClient client = new FileSystemServiceClient();
  16:             client.GetItemsCompleted += new EventHandler<GetItemsCompletedEventArgs>(client_GetItemsCompleted);
  17:             client.GetItemsAsync(this.Path);
  18:         }
  19:         else
  20:             this.IsExpanded = !this.IsExpanded;
  21:     }
  22:  
  23:     private void client_GetItemsCompleted(object sender, GetItemsCompletedEventArgs e)
  24:     {
  25:         this.Items.Clear();
  26:  
  27:         foreach (var item in e.Result)
  28:         {
  29:             if (item is File)
  30:                 this.Items.Add(new FileViewModel(item as File));
  31:             else if (item is Folder)
  32:                 this.Items.Add(new FolderViewModel(item as Folder, this.Path));
  33:         }
  34:  
  35:         this.IsExpanded = true;
  36:     }
  37:  
  38:     // here starts the Binding properties...
  39: }

In this snipped I omitted the Binding properties but remember that IsExpanded, Items and ClickCommand are respectively a boolean that indicated if the node is open or not, a collection of the child nodes and the command the user triggers when he click the node. When this happens, the service is called, and the returned children are loaded into the Items properties. I think the logic is really straightforward.

Finally it is time to watch the XAML code. Using two Implicit Templates, It is really simple to create a hierarchical structure starting from a simple ItemsControl:

   1: <Grid.Resources>
   2:     
   3:     <DataTemplate DataType="vm:FolderViewModel">
   4:         <StackPanel>
   5:             <StackPanel Orientation="Horizontal" Margin="2">
   6:                 <Image Source="/Images/folder.png" Width="16" Height="16" />
   7:                 <HyperlinkButton IsEnabled="{Binding Item.HasChildren}" 
   8:                                  Command="{Binding ClickCommand}" 
   9:                                  Content="{Binding Item.Name}" 
  10:                                  Foreground="Black" />
  11:             </StackPanel>
  12:             <ItemsControl Visibility="{Binding IsExpanded, Converter={StaticResource b2v}}" 
  13:                           Margin="20,0,0,0" ItemsSource="{Binding Items}" />
  14:         </StackPanel>
  15:     </DataTemplate>
  16:     
  17:     <DataTemplate DataType="vm:FileViewModel">
  18:         <StackPanel Orientation="Horizontal" Margin="2">
  19:             <Image Source="/Images/file.png" Width="16" Height="16" />
  20:             <TextBlock><Run Text="{Binding Item.Name}" />(<Run Text="{Binding Item.Size}" /> Kb)</TextBlock>
  21:         </StackPanel>
  22:     </DataTemplate>
  23:     
  24: </Grid.Resources>
  25:  
  26: <ScrollViewer>
  27:     <ItemsControl ItemsSource="{Binding Items}" />
  28: </ScrollViewer>

The DataTamplate relative to the FileViewModel simply presents an image and the TextBlock for the name. The FolderViewModel instead refers to a DataTemplate containing another ItemsControl binded the the Items property. imageThanks to the propagation of the resources this ItemsControl again is able to generate children based on the same templates. Te result is a simple treeview that opens a node when you click on it. The Margin property indents the nodes and improve the TreeView aspect.

The figure on the side shows the final aspect of the treeview, decorated with beautiful images. The best thing is that you can create a lot of different nodes on the basis of the type you add to the collection.

I have to confess, at the first time I've tryied to generate this using a TreeView and a HierarchicalDataTemplate but I was unable to manage to have it working. It seems the HierarchicalDataTemplate does not support the implicit data templates.

The sole trick is given by the Converter I used to change the boolean type to a Visibility property. This let me to use the IExpanded property to show or not the ItemsControl.

If you are intersted in the working sample you can download it here. The code is complete and assumes you bind the service to the C:\ volume.

Download: XPG.ImplicitDataBinding (479Kb)

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

Create a 3d maze with Silverlight 5.0

2012-01-02T01:40:25+01:00 by codeblock

I would like to start this post saying I'm not a game development expert. During the first times of my work with computers I've been fashinated by the matter but I never gone deep on this development branch. Once I've meet the first time Silverlight 5.0 and I known about the 3D programming the first idea I had is to create a very simple maze as the one someone could write as the basis of a 3D game. In this post I want to briefly illustrate the work you can download at the end of the text. Here you can view a short video of the result of my work.

The maze in this video is made totally with the 3D API in Silverlight 5.0 and is totally compatible with the RTW bits. The maze is randomly generated every time you load the program and you can control the movement using the keyboard.

Generate the maze

imageAt the base of the example there is a random generation algorithm. I think there are lot of algorithms you can find on internet and probably the one I used is really simple, but it is really effective.

The maze if based on a square divided in a number of cells and every cell has a wall on every side. Once I decided the size of the side I fill the square of celle and then I choose a random cell on a side. Then I search for an adiacent cell to move to. If the cell exists I remove the walls betweek the two cells then I move to the new position.

The algorithm continue to crawl the cells while there are room to move. If during this loop I meet a position that have not a free adiacent cell I crawl back on my steps searching for some cell to move to. When the position returns to the very first position where I started so the work is finished and all the cells have been used. Here is the core of the algorithm I described:

   1: int progress = 0;
   2:  
   3: Stack<Cell> stack = new Stack<Cell>();
   4: this.Reset();
   5:  
   6: Cell cell = this.GetRandom(0);
   7: cell.Type = CellType.Enter;
   8: cell.Visited = true;
   9:  
  10: while (true)
  11: {
  12:     Cell adiacent = this.GetAdiacentNonVisited(cell);
  13:  
  14:     if (adiacent != null)
  15:     {
  16:         stack.Push(cell);
  17:         adiacent.Visited = true;
  18:         cell = adiacent;
  19:  
  20:         progress++;
  21:  
  22:         this.OnGenerationProgressChanged((int)(progress * 100.0 / (this.Width * this.Height)));
  23:     }
  24:     else
  25:     {
  26:         if (stack.Count > 0)
  27:             cell = stack.Pop();
  28:         else
  29:             break;
  30:     }
  31: }
  32:  
  33: cell = this.GetRandom(this.Height - 1);
  34: cell.Type = CellType.Exit;
  35:  
  36: this.OnGenerationCompleted();

The figure on the side shows the resulting maze that is generated by the algorithm. It is very close to the labyrinths you can find in puzzles magazines.

Create the 3D view

Once the maze has been calculated it is time to render it using Silverlight 3D API. The rendering is made creating a square plan representing the floor of the maze and then iterating over oll the cells and creating the remaining walls.

A wall is exactly a parallelepiped created on a side. Since the thickness of the square side is zero, the wall is created across this line. some point external and some point internal. To avoid gaps in the corners all the walls include the corner of the square, also if another wall already used the same space.

Untitled-1Silverlight 3D API let you create every kind of figure using a collection of edges. The edges are drawed to create triangles.  A triangle is the sole surface you can create connecting three edges, that for sure is part of a single plane. Every other surface you can create can be constructed using a collection of triangles but is not necessarily part of a single plane. So to create the rectangle representing a face of a wall you have to use two triangles.

On the left side you can see the aspect of a wall. The figure shows the triangles that compose the three visible faces of the wall. Remember that the other side has exactly the same faces in the opposite position.

Drawing with the API you have to create the vertices of the figure then create the triangles connecting the vertices with edges. The full collection of edges makes the figure and it is added to a greater collection that represents the entire drawing. This collection is used to draw the final scene. The following snippet shows how to create a single wall:

   1: private void AddWall(List<VertexPositionColor> edges, float xOffset, float zOffset, float xSize, float zSize)
   2: {
   3:     var wall = new List<VertexPositionColor>();
   4:  
   5:     Vector3 topLeftFront = new Vector3(xOffset, this.Height, zOffset + zSize);
   6:     Vector3 bottomLeftFront = new Vector3(xOffset, 0.0f, zOffset + zSize);
   7:     Vector3 topRightFront = new Vector3(xOffset + xSize, this.Height, zOffset + zSize);
   8:     Vector3 bottomRightFront = new Vector3(xOffset + xSize, 0.0f, zOffset + zSize);
   9:     Vector3 topLeftBack = new Vector3(xOffset, this.Height, zOffset);
  10:     Vector3 topRightBack = new Vector3(xOffset + xSize, this.Height, zOffset);
  11:     Vector3 bottomLeftBack = new Vector3(xOffset, 0.0f, zOffset);
  12:     Vector3 bottomRightBack = new Vector3(xOffset + xSize, 0.0f, zOffset);
  13:  
  14:     Color c1 = Color.FromNonPremultiplied(200, 200, 200, 255);
  15:     Color c2 = Color.FromNonPremultiplied(150, 150, 150, 255);
  16:     Color c3 = Color.FromNonPremultiplied(100, 100, 100, 255);
  17:  
  18:     // Front face
  19:     wall.Add(new VertexPositionColor(topRightFront, c1));
  20:     wall.Add(new VertexPositionColor(bottomLeftFront, c1));
  21:     wall.Add(new VertexPositionColor(topLeftFront, c1));
  22:     wall.Add(new VertexPositionColor(topRightFront, c1));
  23:     wall.Add(new VertexPositionColor(bottomRightFront, c1));
  24:     wall.Add(new VertexPositionColor(bottomLeftFront, c1));
  25:  
  26:     // Back face 
  27:     wall.Add(new VertexPositionColor(bottomLeftBack, c1));
  28:     wall.Add(new VertexPositionColor(topRightBack, c1));
  29:     wall.Add(new VertexPositionColor(topLeftBack, c1));
  30:     wall.Add(new VertexPositionColor(bottomRightBack, c1));
  31:     wall.Add(new VertexPositionColor(topRightBack, c1));
  32:     wall.Add(new VertexPositionColor(bottomLeftBack, c1));
  33:  
  34:     // Top face
  35:     wall.Add(new VertexPositionColor(topLeftBack, c2));
  36:     wall.Add(new VertexPositionColor(topRightBack, c2));
  37:     wall.Add(new VertexPositionColor(topLeftFront, c2));
  38:     wall.Add(new VertexPositionColor(topRightBack, c2));
  39:     wall.Add(new VertexPositionColor(topRightFront, c2));
  40:     wall.Add(new VertexPositionColor(topLeftFront, c2));
  41:  
  42:     // Left face
  43:     wall.Add(new VertexPositionColor(bottomLeftFront, c3));
  44:     wall.Add(new VertexPositionColor(bottomLeftBack, c3));
  45:     wall.Add(new VertexPositionColor(topLeftFront, c3));
  46:     wall.Add(new VertexPositionColor(topLeftFront, c3));
  47:     wall.Add(new VertexPositionColor(bottomLeftBack, c3));
  48:     wall.Add(new VertexPositionColor(topLeftBack, c3));
  49:  
  50:     // Right face 
  51:     wall.Add(new VertexPositionColor(bottomRightBack, c3));
  52:     wall.Add(new VertexPositionColor(bottomRightFront, c3));
  53:     wall.Add(new VertexPositionColor(topRightFront, c3));
  54:     wall.Add(new VertexPositionColor(bottomRightBack, c3));
  55:     wall.Add(new VertexPositionColor(topRightFront, c3));
  56:     wall.Add(new VertexPositionColor(topRightBack, c3));
  57:  
  58:     edges.AddRange(wall);
  59: }

When the entire scene has been created it is time to draw it to the viewport. While you are drawing the scene, the collection of edges does not change anymore because it represents the object to draw on the 3D space. What really changes is the position from where the scene is viewed. This position is a vector located in the 3D space and have a direction to it points. Imagine it as your eye pointing a direction in the space that plus or minus is the direction pointed by your nose. Another important component of a scene is the light source. My example uses a omnidirectional light source but for the sake of simplicity I will leave this argument open. So here is the code that create the scene.

   1: XNA3DMazeRenderer renderer = 
   2:     new XNA3DMazeRenderer(System.Windows.Media.Colors.Red, (float)this.CellSize, 5.0f);
   3:  
   4: IEnumerable<VertexPositionColor> edges = renderer.Render(this.Maze);
   5:  
   6: this.Buffer = new VertexBuffer(
   7:     GraphicsDeviceManager.Current.GraphicsDevice,
   8:     VertexPositionColor.VertexDeclaration,
   9:     edges.Count(),
  10:     BufferUsage.WriteOnly);
  11:  
  12: this.Buffer.SetData(0, edges.ToArray(), 0, edges.Count(), 0);

Then the code that creates/updates the camera. It is full of matricial maths but it simply creates two points on the space and then connect one to the other. The first is the position of the camera and the second is the position of the target pointed by the camera:

   1: private void UpdateCamera()
   2: {
   3:     float x = (float)(this.CellSize * this.Maze.Width * this.Observer.Position.X);
   4:     float y = (float)(this.CellSize * this.Maze.Height * this.Observer.Position.Y);
   5:     float course = (float)(this.Observer.Course * (Math.PI / 180.0));
   6:     float tilt = (float)(this.Observer.Tilt * (Math.PI / 180.0));
   7:     Vector3 cameraPosition = new Vector3(x, 3.0f, y);
   8:     System.Windows.Point target = 
   9:         new System.Windows.Point(x + Math.Sin(course) * 100.0, y + Math.Cos(course) * 100.0);
  10:     float elevation = (float)(3.0 + Math.Sin(tilt) * 100.0);
  11:     Vector3 cameraTarget = new Vector3((float)target.X, elevation, (float)target.Y);
  12:  
  13:     this.View =
  14:         Matrix.CreateLookAt(cameraPosition, cameraTarget, Vector3.Up);
  15: }

As you can see in the code I use an "Observer" object that represents the player in the maze. It has a X and Y position on the 2D surface of the game, a course from 0 to 360 degrees representing the direction to it is pointing and finally a Tilt property that is used to move up and down. These properties are connected with the keyboard actions and determines the movement of the player onto the game surface.

Moving the player and making walls solid

Viewing the maze rendered the first time is for sure wonderful, but the very great thing is being able to navigate inside it with the keyboard. Every time a property of the Observer object is updated the change is reflected externally with the Change event. The event cause the update of the camera position and then the redraw of the scene. Using up and down arrow you can move forward and backward and with left and right arrows it is possible to turn the course in these directions. Additionally you can use PageUp and PageDown to tilt up and down the camera as the player tilt the head.

To catch the keyboard events continuously I use a trick. This is because keyboard event in silverlight does not repeats automatically. Using a KeyboardState class I created I check for KeyUp and KeyDown changing the status of monitored keys. Then a timer changed the observer properties according with the pressed keys. This tecnique allows also to use more that a single key at a time allowing the observer to turn since it is moving forward.

Finally you have to face another problem. While you are moving you have to check for the presence of a wall and cancel the motion when the observer hits it. Without this check the observer will pass through walls missing a great part of the realistic representation of the scene. The following code tests the presence of a wall and eventually cancel the movement:

   1: private void Observer_Changing(object sender, ObserverChangingEventArgs e)
   2: {
   3:     double x = this.Maze.Width * this.CellSize * e.Position.X;
   4:     double y = this.Maze.Height * this.CellSize * e.Position.Y;
   5:  
   6:     Cell cell = this.Maze.CellAt(
   7:         (int)(this.Maze.Width * e.Position.X),
   8:         (int)(this.Maze.Height * e.Position.Y));
   9:  
  10:     Rect boundaries = new Rect(
  11:         cell.X * this.CellSize + 1.25,
  12:         cell.Y * this.CellSize + 1.25,
  13:         this.CellSize - 2.5,
  14:         this.CellSize - 2.5);
  15:  
  16:     e.Cancel = false;
  17:  
  18:     if (cell.Top.IsSolid && y < boundaries.Top) e.Cancel = true;
  19:     if (cell.Bottom.IsSolid && y > boundaries.Bottom) e.Cancel = true;
  20:     if (cell.Left.IsSolid && x < boundaries.Left) e.Cancel = true;
  21:     if (cell.Right.IsSolid && x > boundaries.Right) e.Cancel = true;
  22: }

The collision algoritm here is very simple. It creates a buffer around the walls of the cell where the observer is located and then tests if the position goes out of these boundaries.

Working with 3D

Working with 3D in silverlight is for sure interesting but it requires a good knowledge of 3D math to achieve good results. Every time you get something really effective since it is a low level API using it programming interface becomes mostly difficult. So if you need to work with 3D I suggest to use an hi level framework that abstracts the API and let you think in terms of solid figures instead of collection of edges. Balder is for sure a good example of what I mean: http://balder.codeplex.com/

Download: http://www.silverlightplayground.org/assets/sources/SLPG.Maze.zip (270kb)

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

Silverlight 5.0 is here to stay!

2011-12-09T21:25:11+01:00 by codeblock

Silverlight-5Just a few minutes ago I’ve received the good news about the release of Silverlight 5.0 RTW. This is the release many of us are expecting for the end of the year as stated in some previous events. Silverlight 5.0 is a great big step forward on the development of business applications due to a number of improvements introduced in this technology.

These improvements involve full-trust, databinding, P/Invoke, Multiple windows and the introduction of the new 3d API based on XNA. For a complete list of the new features please visit Pete Brown’s blog where you can find an useful index with many examples linked.

By my side I’m planning to start writing about the new feature asap, waiting just the time of making my experiments to become usable examples. Probably I will post about 3d in the next days.

For now please let me make my compliments to the Silverlight team to be able to deliver this release despite of the continuous voices spreading arount about the death of this technology. Now we can say that Silverlight is a mature technology we can start use everywhere we need to easily deliver powerful business applications developed as fast as the light.

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

Silver VNC 1.0 for Windows Phone "Mango"

2011-11-18T23:21:55+01:00 by codeblock

Thanks to the new release of Windows Phone 7.1 "Mango", I've finally managed to publish the first release of Silver VNC 1.0. This version is made with the sources I've created for Silverlight 4.0 and published on codeplex at http://silvervnc.codeplex.com/.

Silver VNC 1.0 running on HDC HD7

On the left side I've posted a short video to show the capabilities of the Free Edition.

With Silver VNC free edition you can remotely view the desktop of a computer with the popular and free RFB protocol. You can easily install a VNC server downloading one of the known free versions like Real VNC, Ultra VNC and so on.

Please enjoy the application for free downloading it from the Windows Phone marketplace. I'm currently working on the next version that allows to send commands to the computer.

Consume a Socket using Reactive Extension

2011-06-29T09:43:23+01:00 by Andrea Boschin

In my last post I wrote about writing a TCP server using the Reactive Extensions library. It was not a Silverlight related post, but it simply introduces the server side component that I will use in this post to show you how to use the same library to consume the incoming data and present it in Silverlight. The interesting part is to understand how rx can simplify the programming model when dealing with asynchronicity both in Silverlight and in server side full .NET programming.

The server I presented was a very simple socket listener that waits for connections and then, when the channel has been established, it push to the client a continuous stream of data that represent the current state of the CPU and memory of the server. With this huge amount of informations incoming we can create a little application that is able to show a chart and some gauges, updated almost in realtime.

The application, developed following the MVVM pattern, is made of a simple view containing the controls used to present the informations. These controls are feeded by a couple of properties in the ViewModel that are updated with the incoming data. So the most of the work is done by the ViewModel that is responsible of connecting to the socket and read the information stream to update the properties. In a real world solution probably you will have some kind of layer between the ViewModel and the socket, but for the sake of the post we will keep it simple as much as we need to understand how it works.

Consuming a socket in Silverlight means using an instance of the Socket class that represents the connection and a SocketAsyncEventArgs that is used when you call the methods of the connection to make the requests and receive responses. So, as an example, when you have to establish the connection you have to create the instance of the Socket class and the call the ConnectAsync method providing the SocketAsyncEventArgs initialized with the address of the endpoint to connect to. When the connection has been established the SocketAsyncEventArgs class will raise a Completed event that notify about the result of the operation. Doing it with Reactive Extensions mean something like this:

   1: protected void Connect()
   2: {
   3:     this.Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
   4:  
   5:     SocketAsyncEventArgs arguments = new SocketAsyncEventArgs();
   6:     arguments.RemoteEndPoint = new DnsEndPoint(Application.Current.Host.Source.DnsSafeHost, 4530);
   7:  
   8:     var socketAsObservable = from args in Observable.FromEvent<SocketAsyncEventArgs>(
   9:                                  ev => arguments.Completed += ev,
  10:                                  ev => arguments.Completed -= ev)
  11:                              select args.EventArgs;
  12:  
  13:     socketAsObservable
  14:         .Where(args => args.LastOperation == SocketAsyncOperation.Connect)
  15:         .Subscribe(
  16:         args =>
  17:         {
  18:             args.Dispose();
  19:             this.Receive();
  20:         });
  21:  
  22:     this.Socket.ConnectAsync(arguments);
  23: }

In the line #3 it is created the Socket with the common parameter that is used in Silverlight for a TCP channel. Then an instance of the SocketAsyncEventArgs is initialized and its property RemoteEndPoint is provided with and instance of DnsEndPoint that represente the address of the server to connect to. The port is 4530 like we defined in the previour article.

At this point it is created a stream, called socketAsObservable, from the Completed event of the SocketAsyncEventArgs. the stream filter the LastOperation to be "Connect", as we expect and in the Subscribe method disposes the SocketAsyncEventArgs instance and starts to receive data. The SocketAsyncEventArgs instance can be used only once so we have to carefully dispose it to avoid memory leaks.

Once the connection has successfully established you have to put your socket in Receive. When incoming data is detected you will be notified and you can fetch it from the SocketAsyncEventArgs and put again the socket in Receive. Here is how it appear with Reactive Extensions:

   1: protected void Receive()
   2: {
   3:     SocketAsyncEventArgs arguments = new SocketAsyncEventArgs();
   4:     arguments.SetBuffer(new byte[1024], 0, 1024);
   5:  
   6:     var socketAsObservable = from args in Observable.FromEvent<SocketAsyncEventArgs>(
   7:                                  ev => arguments.Completed += ev,
   8:                                  ev => arguments.Completed -= ev)
   9:                              select args.EventArgs;
  10:  
  11:     socketAsObservable
  12:         .Where(args => args.LastOperation == SocketAsyncOperation.Receive)
  13:         .Throttle(TimeSpan.FromMilliseconds(500))
  14:         .ObserveOnDispatcher()
  15:         .Subscribe(OnReceive);
  16:  
  17:     if (this.Socket.Connected)
  18:         this.Socket.ReceiveAsync(arguments);
  19: }

Once again we create the instance of the SocketAsyncEventArgs. It is now initialized with a SetBuffer that allocates a buffer of 1 KByte that is used by the socket to compy the incoming data. Then the socketAsObservable is created using the FromEvent; This method is important because it is in charge of attaching and detaching the Completed event so we avoid to have unwanted delegates around. Again the socketAsObservable is filtered selecting only when LastOperation equals to Receive and we also apply a Throttling of about 500 milliseconds. It is made to discart updated when they are too fast. One update every half a second suffice to say that the UI is up to date with the server.

Fially we marshal the stream to the UI Thread using the ObserveOnDispatcher and the received events are forwarded to the OnReceive method that is responsible of parsing the received data and updating the UI.

   1: protected void OnReceive(SocketAsyncEventArgs args)
   2: {
   3:     string data = Encoding.UTF8.GetString(args.Buffer, 0, args.BytesTransferred);
   4:  
   5:     IEnumerable<Sample> samples = this.GetSamples(ref data);
   6:  
   7:     Array.Clear(args.Buffer, 0, 1024);
   8:  
   9:     if (data.Length > 0)
  10:     {
  11:         byte[] bytes = Encoding.UTF8.GetBytes(data);
  12:         Array.Copy(bytes, args.Buffer, bytes.Length);
  13:         args.SetBuffer(bytes.Length, 1024 - bytes.Length);
  14:     }
  15:     else
  16:         args.SetBuffer(0, 1024);
  17:  
  18:     if (this.Socket.Connected)
  19:         this.Socket.ReceiveAsync(args);
  20:  
  21:     this.Update(samples);
  22: }

The method peek up the received data and then calls again the ReceiveAsync method of the connection to make again the channel ready to receive other informations. Then the Update method is called to update the properties binded to the view.

The code is simple and obviously it need some additional check, as an example it needs to verify the communication errors that here are swallowed. I hope it shows, once again, how reactive extension can help you to simplify the consumption of asynchronous streams.

A TCP Server with Reactive Extensions

2011-06-17T14:17:05+01:00 by codeblock

I know, from the title of this post you may understand that the topic I’m about to cover is not really Silverlight related. Please be patient and it will become clear that there is a relation with Silverlight in the next part when I will complete my exposition.

After a long pause, today I return to the Reactive Extensions, I’ve temporarily shelved for lack of time, and I want to present the implementation of a little server that uses a socket and takes advantage of the Extensions. A socket server usually listens to a TCP port and it can be easily consumed by a Silverlight application. This is not a usual scenario because often it is hard to get rid of firewalls and security people in a company, so the use of HTTP is way better in most of the cases. But, sometimes, tipically when you need a reactive communication that let the application to be always up to date with events on the server, the use of a Socket is an effective soluzione

For such people that are not aware of how a socket server works, a brief explanation. A regular socket server usually opens a port on the address it is binded. The port is represented by a number between 1024 and 65535 (numbers lower than 1024 are reserved) and it is expressed after the ip or dns name separated by a colon.

The server initially reserves the port and starts to listen for incoming connections. Until the arrive of a connection the server is substantially idle but when the connection is detected it has to "accept" the request and initialize the channel that will be used by both the parts to exchange the informations.

The acceptance phase of the server must handle the new connection like it is a completely new channel, so the problem is that the server will have a main channel where it accept connections and a number of channels, one for each client that has requested the connection. Usually this means that the server must spawn a new thread for each connection it accepts and the thread will separately handle its channel leaving the main thread free of returning to the listening phase.

Using Reactive Extension properly makes these operations very easy and the code required to handle the listening and acceptance is really compact. In my sample I use a Console Application that starts the listening ad finally remain available until someone hit enter and definitely closes the application. In the following box the main function:

   1: static CancellationTokenSource cts = new CancellationTokenSource();
   2:  
   3: /// <summary>
   4: /// Mains the specified args.
   5: /// </summary>
   6: /// <param name="args">The args.</param>
   7: static void Main(string[] args)
   8: {
   9:     if (IPAddress.Loopback != null)
  10:     {
  11:         TcpListener listener = new TcpListener(IPAddress.Loopback, 4530);
  12:         listener.Start();
  13:  
  14:         Console.WriteLine("Service is listening on {0} port {1}.", IPAddress.Loopback, 4530);
  15:         Console.WriteLine("Press enter to stop");
  16:  
  17:         Func<IObservable<TcpClient>> accept =
  18:             Observable.FromAsyncPattern<TcpClient>(listener.BeginAcceptTcpClient, listener.EndAcceptTcpClient);
  19:  
  20:         accept()
  21:             .Where(o => o.Connected)
  22:             .ObserveOn(Scheduler.NewThread)
  23:             .Subscribe(acceptedClient => OnAccept(acceptedClient, accept));
  24:  
  25:         Console.ReadLine();
  26:         cts.Cancel();
  27:     }
  28: }

In the first lines the server binds to the port 4530 of the localhost ip (127.0.0.1) and it starts to listen using the Start method. Then using the FromAsyncPattern method it is created an observable source that will notify once a new connection is detected. The observable will give the channel ready to communicate. So, the Subcribe method forward the channel to the OnAccept method that is responsible to feed the channel with informations retrieved by the computer (in this case if gives cpu usage and memory size in realtime). Obviously this is the operation we should spawn in a separate thread and the trick here is done by the ObserveOn(Scheduler.NewThread) that automatically initialize and start the thread using the body of the OnAccept method. Let me continue with the OnAccept method:

   1: static void OnAccept(TcpClient client, Func<IObservable<TcpClient>> accept)
   2: {
   3:     accept()
   4:         .Where(o => o.Connected)
   5:         .ObserveOn(Scheduler.NewThread)
   6:         .Subscribe(acceptedClient => OnAccept(acceptedClient, accept));
   7:  
   8:     Console.WriteLine("channel opened");
   9:  
  10:     while (!cts.Token.WaitHandle.WaitOne(100))
  11:     {
  12:         try
  13:         {
  14:             if (client.Connected)
  15:             {
  16:                 byte[] message = GetMessage();
  17:                 client.Client.Send(message);
  18:             }
  19:         }
  20:         catch (Exception ex)
  21:         {
  22:             Console.WriteLine(ex.Message);
  23:             break;
  24:         }
  25:     }
  26:  
  27:     Console.WriteLine("channel closed");
  28:     client.Close();
  29: }

As you can see the OnAccept method receives the connected TcpClient side by side with the instance of the observable and in the very first lines puts the main thread again on listen, just before starting its work. This operation closes the loop because the listener will continue to wait for new connections and the new thread will send the informations along the channel.

To gracefully handle the closure of the server, once you hit the enter key a CancellationTokenSource is used to forward to alle the threads the request of exit. The method GetMessage simply reads the informations of cpu and memory and translates them to a byte array that is sent on the channel.

   1: const ulong Mega = 1048576;
   2: static PerformanceCounter cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total");
   3:  
   4: static byte[] GetMessage()
   5: {
   6:     ulong totalPhisicalMemory = 0;
   7:     ulong availablePhisicalMemory = 0;
   8:     ulong totalVirtualMemory = 0;
   9:     ulong availableVirtualMemory = 0;
  10:     float cpu = cpuCounter.NextValue();
  11:  
  12:     NativeMethods.MEMORYSTATUSEX memStatus = new NativeMethods.MEMORYSTATUSEX();
  13:  
  14:     if (NativeMethods.GlobalMemoryStatusEx(memStatus))
  15:     {
  16:         totalPhisicalMemory = memStatus.ulTotalPhys / Mega;
  17:         availablePhisicalMemory = memStatus.ulAvailPhys / Mega;
  18:         totalVirtualMemory = memStatus.ulTotalVirtual / Mega;
  19:         availableVirtualMemory = memStatus.ulAvailVirtual / Mega;
  20:     }
  21:  
  22:     return Encoding.UTF8.GetBytes(
  23:         string.Format(
  24:             CultureInfo.InvariantCulture,
  25:             "{0:0.0}:{1}:{2}:{3}:{4}{5}",
  26:             cpu,
  27:             totalPhisicalMemory,
  28:             availablePhisicalMemory,
  29:             totalVirtualMemory,
  30:             availableVirtualMemory,
  31:             Environment.NewLine));
  32: }

To have a try with the server please runs the code and then open a command prompt and type the following

telnet 127.0.0.1 4530
 

You will see a continuous stream of informations displayed on the console and you can also try to run multiple command prompt with the same instruction and all the connections will be connected. This example shows the powerfulness of the reactive extensions. In the next post I will show you how to use the library to consume this socket.

The Reactive Snake for Windows Phone 7

2011-05-04T22:57:43+01:00 by codeblock

CaptureContinuing my experiments with Reactive Extension I put together a small example that show an alternative use of the library to create a little game. The game is the widely known Snake that many of us have played on his own Nokia when it is the sole game in the ancient models. Please take note that the game I wrote is not complete since it is first of all an example of the use of a technology and how it can simplify the development of a slightly complex logic like the one that is behind this game.

The core of the game is based on two separate uses of the Reactive Extensions. From one side I have a main loop that is based on a frequent timeout that in a complete version of the game could be used to change the game speed. In this version it is set to 75 milliseconds. Every time the timeout is elapsed I move forward the Snake of one position saved in two variables XDirection and YDirection. This variable can assume the values of 1 or -1 if the snake is moving along the direction and 0 if the snake is moving along the opposite direction.

Using this variables the GenerateWithTime method of the RX generate a stream of points that are the positions where the Snake have passed during its move. The length of the snake is determined by the TrailWhile method that evaluate the length using a third variable that is incremented every time the Snake eats a gem.

The other use of the RX is to handle the Manipulation events that are used to detect if the user touches the screen basing on this touches the XDirection and YDirection are updated to reflect the touch. As an example if when the snake is moving along the y axis like the screenshot the touch on the right side of the screen make change the direction to right and the touch on the left to left.

Here is the code of the main game loop:

Observable.GenerateWithTime(
    new Point(0, 0),
    p => this.IsRunning,
    p => p,
    p => TimeSpan.FromMilliseconds(75),
    p => this.NewPoint(p))
    .ObserveOnDispatcher()
    .TrailWhile(o => o > this.Length)
    .Subscribe(this.EvaluateAndDrawSnake);
 
private Point NewPoint(Point point)
{
    double x = point.X + XDirection;
    double y = point.Y + YDirection;
 
    if (x < 0) x = 22;
    if (x > 22) x = 0;
    if (y < 0) y = 36;
    if (y > 36) y = 0;
 
    return new Point(x, y);
}

The method EvaluateAndDraw is the part of the code that check when the snake eats itself to end the game and then redraw the snake on the screen. Here is the management of the screen:

Observable.FromEvent<ManipulationStartedEventArgs>(
    ev => this.ManipulationStarted += ev,
    ev => this.ManipulationStarted -= ev)
    .Select(
    o =>
    {
        return new
        { 
            X = Math.Sign(o.EventArgs.ManipulationOrigin.X - 240), 
            Y = Math.Sign(o.EventArgs.ManipulationOrigin.Y - 400) 
        };
    })
    .Subscribe(
    o =>
    {
        if (this.XDirection != 0 && this.YDirection == 0)
        {
            this.XDirection = 0;
            this.YDirection = o.Y != 0 ? o.Y : this.YDirection;
        }
        else if (this.XDirection == 0 && this.YDirection != 0)
        {
            this.XDirection = o.X != 0 ? o.X : this.XDirection;
            this.YDirection = 0;
        }
    });

The following link lets you download the complete source of the example. My highest score is 510. Have a good game.

Download: SLPG.ReactiveSnake.zip (140kb)

Silverlight 5.0: Custom Markup Extensions and Roles

2011-04-23T00:54:32+01:00 by codeblock

Starting from Silverlight 5.0 you can create custom Markup Extensions and this is an interesting feature to easily encapsulate some logic and make it easy to be applied to properties in the XAML markup. Until now you could only use a few extensions to apply resources (StaticResource), make databinding (Binding) and connect properties with parts of a template (TemplateBinding) but now, implementing a really simple interface you can build your own.

   1: public interface IMarkupExtension<out T> where T: class
   2: {
   3:     T ProvideValue(IServiceProvider serviceProvider);
   4: }

Using this interface you can specify the type to which the markup extension can be applied (the generic type T) but if you do not need a control about this type you can extend the MarkupExtension abstract class that is like you are extending IMarkupExtension<object>.

Inside the ProvideValue method there is the whole logic of the extension and using the IServiceProvider passed by the runtime you can get access to three services that let you get some informations about the markup where the extension is located.

IRootObjectProvider: provide a reference to the Root object of the VisualTree which the element is part of

IXamlTypeResolver : is able to resolve the name of the tags in the markup to the corresponding type.

IProvideValueTarget : gets a reference to the property and the elements which the markup extension is assigned

To retrieve an instance of this services you can use the GetService method on the IServiceProvider instance.

IProvideValueTarget target = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));

In this example I wrote a RoleBinding extension that a developer can use to connect parts of the User Interface with a Validator class that is able to authorize the access to these parts using a set of custom rules. Let start writing the markup extension:

   1: using System;
   2: using System.Net;
   3: using System.Windows;
   4: using System.Windows.Controls;
   5: using System.Windows.Documents;
   6: using System.Windows.Ink;
   7: using System.Windows.Input;
   8: using System.Windows.Media;
   9: using System.Windows.Media.Animation;
  10: using System.Windows.Shapes;
  11: using System.Windows.Markup;
  12: using System.Security.Principal;
  13: using System.Windows.Data;
  14: using System.Xaml;
  15: using System.ComponentModel;
  16: using System.Diagnostics;
  17: using System.Security;
  18: using System.Reflection;
  19: using System.Globalization;
  20:  
  21: namespace SLPG.MarkupExtensions
  22: {
  23:     public class RoleBindingExtension : MarkupExtension
  24:     {
  25:         /// <summary>
  26:         /// Gets or sets the name of the group.
  27:         /// </summary>
  28:         /// <value>
  29:         /// The name of the group.
  30:         /// </value>
  31:         public string GroupName { get; set; }
  32:         /// <summary>
  33:         /// Gets or sets the name of the feature.
  34:         /// </summary>
  35:         /// <value>
  36:         /// The name of the feature.
  37:         /// </value>
  38:         public string FeatureName { get; set; }
  39:         /// <summary>
  40:         /// Gets or sets the converter.
  41:         /// </summary>
  42:         /// <value>
  43:         /// The converter.
  44:         /// </value>
  45:         public IValueConverter Converter { get; set; }
  46:         /// <summary>
  47:         /// Gets or sets the converter parameter.
  48:         /// </summary>
  49:         /// <value>
  50:         /// The converter parameter.
  51:         /// </value>
  52:         public object ConverterParameter { get; set; }
  53:  
  54:         /// <summary>
  55:         /// Provides the value.
  56:         /// </summary>
  57:         /// <param name="serviceProvider">The service provider.</param>
  58:         /// <returns></returns>
  59:         public override object ProvideValue(IServiceProvider serviceProvider)
  60:         {
  61:             IProvideValueTarget target = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));
  62:  
  63:             bool isAuthorized = false;
  64:  
  65:             if (RoleManager.Current != null)
  66:                 isAuthorized = RoleManager.Current.Validator.Authorize(this.GroupName, this.FeatureName);
  67:             else
  68:                 isAuthorized = true;
  69:  
  70:             if (this.Converter != null)
  71:                 return this.MapToType(isAuthorized, target, this.Converter, this.ConverterParameter);
  72:  
  73:             return this.MapToType(isAuthorized, target);
  74:         }
  75:  
  76:         /// <summary>
  77:         /// Maps to type.
  78:         /// </summary>
  79:         /// <param name="isAuthorized">if set to <c>true</c> [is authorized].</param>
  80:         /// <param name="target">The target.</param>
  81:         /// <param name="converter">The converter.</param>
  82:         /// <param name="converterParameter">The converter parameter.</param>
  83:         /// <returns></returns>
  84:         private object MapToType(bool isAuthorized, IProvideValueTarget target, IValueConverter converter, object converterParameter)
  85:         {
  86:             PropertyInfo info = target.TargetProperty as PropertyInfo;
  87:  
  88:             if (info != null)
  89:                 return converter.Convert(isAuthorized, info.PropertyType, converterParameter, CultureInfo.CurrentCulture);
  90:  
  91:             return isAuthorized;
  92:         }
  93:  
  94:         /// <summary>
  95:         /// Maps to type.
  96:         /// </summary>
  97:         /// <param name="isAuthorized">if set to <c>true</c> [is authorized].</param>
  98:         /// <param name="target">The target.</param>
  99:         /// <returns></returns>
 100:         private object MapToType(bool isAuthorized, IProvideValueTarget target)
 101:         {
 102:             PropertyInfo info = target.TargetProperty as PropertyInfo;
 103:  
 104:             if (info != null)
 105:             {
 106:                 if (info.PropertyType == typeof(Visibility))
 107:                     return isAuthorized ? Visibility.Visible : Visibility.Collapsed;
 108:             }
 109:  
 110:             return isAuthorized;
 111:         }
 112:     }
 113: }

First of all I extend the MarkupExtension class. The core of the extension is the ProvideValue method. Inside this method I get a service that implements the IProvideValueTarget interface to retrieve informations about the property where the extension is applied to. In my case I need to know the type of the property because I have to map the boolean information (true means authorized, false means not authorized) to the property. For example if the target property is Visibility I map the true to Visible and false to Collapsed.

A markup extension can have a number of parameters. They are public properties exposed by the class. Differently from other existing extensions the custom extensions cannot have unnamed parameters. This is a choice of the Silverlight team I hope will change in future releases just to make extensions very close to the WPF ones. In my case the extension support these parameters:

GroupName and FeatureName: two strings that are used to select the feature and the category of feature the element is part. You can specify for example "Products" as GroupName and "Create" as feature. The values and their meaning are completely up to you. By default they are interpreted as role names where the two parts are joined by a dot: GroupName.FeatureName.

Converter and ConverterParameter: like the Binding extension it is a class that implements IValueConverter and a parameter passed to the class during the conversion. It is used to apply custom conversion to the boolean value that comes from the Validator. In the code provided with the post I use a converter to map the boolean to a Color (Red or Green). 

The extension rely on a Lifetime Object that contains the roles granted to the current user. In my example these roles are passed using the InitParams but please do not repeat this in a production environment because a malicious user can easily impersonate different roles. Probably the better thing  is to use an AuthorizationDomainService provided by the WCF RIA Services.

Once you add the RoleManager service to the App.xaml you can also specify a custom validator that will get the authorization requests and can apply every type of logic you need to perform the authorization. This class can be easily created by implementing the IRoleManagerValidator interface.

You can download the code of this article using the following link. I appreciate every suggestion to improve this extension.

Download: SLPG.MarkupExtensions.zip (30KB)

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

Silverlight 5.0: Plotting beautiful 3D functions

2011-04-13T19:24:00+01:00 by codeblock

1Following the announcement made today on the scene on MIX 2011 I’ve prepared an example for the purpose of showing the new powerful 3D available in the beta bits. Remembering ancient days when I enjoyed myself writing small programs to plot 3D functions on the screen of my Amiga 500, I decided to follow again this path and put together a few lines of code to draw the sample functions in Silverlight (so this pairs with the fractals experiments made in occasion of MIX 2009).

Drawing 3D scenes in Silverlight is not so intuitive as it is in WPF due the fact that the API exposed by the plugin is on a lower level than the WPF one. The team choosed to implement an API that is very close to the XNA framework one. So to create objects in 3D space you have to deal with lot of triangles, vertex and pixel shaders and other exotic stuff. Nonetheless, once you understand the way the thing works the results don’t delude you.

Basically to create a 3D scene you have to put in the markup a special element named DrawingSurface. This element is able to render a 3D set. Every time it surface needs to be rendered it raises an OnDraw event passing to the handler and instance of a GraphicsDevice that is useful to actually draw the scene on the surface. In the example a class named Scene is used to setup the 3D environment (camera, viewing direction and elements in the scene) do inside the OnDraw event the Scene’s Draw method is called to perform the draw.

2Inside the Scene class every element draw itself. In my case the scene is populated only by FunctionPlot class that contains the function to draw and receives some parameters. During the rendering is is possible to apply some transformation matrices that apply rotation, translation and scaling.

The drawing of the function is probably the simplest thing. While the x and y coordinates run on the plane the vertexs of a square are build. The area of every square is divided in two triangles.

A detailed explanation of how the 3D pipeline works is out of the scope of this article and should take an huge number of posts, not few lines. For now I give you the code I wrote for this example and I hope you appreciate like me the beautiful images that it creates.

Download: SLPG.3D.zip (256kb)

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

Taking advantage of combining different streams using Reactive Extension's:

2011-04-04T16:18:45+01:00 by Andrea Boschin

One interesting feature of Reactive Extensions is the combining of Observables. There are a number of extension methods made to combine two or more streams; Amb, Concat, SelectMany, Merge, Zip, CombineLatest, all these methods are made to take, multiple and non necessarily omogeneous, streams and combine them in a unique resulting stream based on different rules. Here a brief resume of the rules applied from every method

Amb returns the stream that start providing values by first
Concat chain two streams one to the end of the other and create a single output
SelectMany Returns every value from the second stream for each value from the first
Merge returns the two streams merged basing of when each source returns its value
Zip returns values from one stream paired with values from another, only when a couple is available.
CombineLatest Combine two streams returning always the latest from both, for each occurrence of a value.

 

Understanding the meaning of each method is really difficult if you do not make some simple experiment, but this is out of the scope of this post. Now I would like to show the meaning of "combining two streams" with a real example that show how a little change in the previous mouse trail example can give a great difference in terms of functions.

In my last example I used the TrailWithCount and TrailWithTime methods to catch MouseMove events to draw a polyline on the plugin that il the trail of the mouse pointer. In the example you have seen the trail shortens while the mouse was moving but when the mouse stops also the trail stops. Now I want to change the example to let the trail shorten to zero length when the mouse stops moving.

To achieve this result I need to have a timer that continues to record the current position for the mouse when it stops. For this purpose I can use the static method Obsevable.Interval(timespan) that is able to generate a stream of events at the given interval of time. Here is the two lines I have to add to the previous example.

   1: Observable.FromEvent<MouseEventHandler, MouseEventArgs>(
   2:     ev => new MouseEventHandler(ev),
   3:     ev => this.LayoutRoot.MouseMove += ev,
   4:     ev => this.LayoutRoot.MouseMove -= ev)
   5:     .CombineLatest(Observable.Interval(TimeSpan.FromMilliseconds(25)), (a, b) => a)
   6:     .ObserveOnDispatcher()
   7:     .Select(o => o.EventArgs.GetPosition(this.LayoutRoot))
   8:     .TrailWithCount(100)
   9:     .Subscribe(DrawLine);

the CombineLatest method gets events from the mouse and from the time interval (this regularly every 25 milliseconds) and using the selector lambda it takes from the combined stream only the mouse events. Every time an interval expire the combined value will contain an integer (the number of intervals from the start) and the latest mouse event. When the mouse stops moving the stream from the MouseMove also stops to provide values but the CombineLatest method will replicate the latest value taken for every interval elapsed. So the trail will be feeded with the latest position and the visual effect will be the shorten of the trail until it reaches the current position of the mouse pointer.

The ObserveOnDispatched method is required because the Observable.Interval method implies the use of a separate thread so when we get the values we are in this thread and we need to marshall back to the UI thread. This method does the trick. Here is the result:

Get Microsoft Silverlight

TrailWithcount and TrailWithTime: the regular way but with performance impact

2011-04-01T14:19:47+01:00 by Andrea Boschin

Today @saldoukhov pointed me to an alternative (and possibly regular) way to implement TrailWithCount, different from the version I introduced yesterday in my latest post. This tecnique invole the use of a bunch of methods from the Reactive Extensions and, at first sight may result more simple and straightforward. Also if @saldoukhov pointed to the sole count version it is also possibile to write a TrailWithTime this way. Here is the new implementation of these methods:

   1: // BE AWARE THAT THESE METHODS HAVE HUGE PERFORMANCE IMPACT
   2:  
   3: public static IObservable<IEnumerable<T>> TrailWithCount<T>(this IObservable<T> observable, int count)
   4: {
   5:     return observable.Scan(
   6:         Enumerable.Empty<T>(),
   7:         (a, b) => a.StartWith(b).Take(count));
   8: }
   9:  
  10: public static IObservable<IEnumerable<T>> TrailWithTime<T>(this IObservable<T> observable, TimeSpan timeSpan)
  11: {
  12:     return observable
  13:         .Select(o => new Timestamped<T>(o, DateTime.Now))
  14:         .Scan(
  15:             Enumerable.Empty<Timestamped<T>>(), (a, b) =>
  16:                 a.StartWith(b).TakeWhile(o => (DateTime.Now - o.Timestamp).TotalMilliseconds <= timeSpan.TotalMilliseconds))
  17:         .Select(k => k.Select(o3 => o3.Value));
  18: }

Both the methods work the same way with the sole difference that the TrailWithTime wraps the Point in a Timestamped instance and then unwraps it just before returning to the caller. Here the Scan method is an aggregation function that forward every occurrence from the stream and populate a resulting aggregation. So the StartWith method let the aggregation grow and then the Take method extract the "counted" instances we really need.

The problem here is that if you try to run this method on a very large number of items (e.g. 1000) you will see a huge performance impact that leave the start of the trail far from the mouse pointer. The effect is so far more evident if you try to use the TrailWithTime with a long timeout (e.g. 5/10 sec).

As far as I understood these methods have an huge payload in terms of iterations and of garbage they produce. Every time you get an event on the stream a new instance of the array is created and it is crawled to create the result. The TrailWithTime has the worst performances because it produces a great number of Timestamped<> instances. I'm not aware of the inner working of the Scan, StartWith and Take methods but the resulting effect is really clear

If you try to run my previous version with a similar interval you will see a very tiny performance impact. Internally I use a queue and the sole payload are the collection of the Dequeued items (but they would have been collected the same if there is not the trail) and the iteration along the resulting collection to create a PointCollection. This is an interesting demonstration of how the use of LINQ may affect drammatically the performances of an application and I suggest you to double check when you use them.

By the way, thanks to @saldoukhov for his suggestion that I had not considered when I wrote for the first time my Trail methods.

Writing TrailWithCount and TrailWithTime methods with Reactive Extensions (and incidentally drawing a mouse trail)

2011-04-01T00:05:38+01:00 by codeblock

I have to confess, the more I play with reactive extensions the more I enjoy the result I get and appreciate their power. With this post I would like to show how it is possible to  take advantage of these extensions to easily obtain something that normally requires a complex code. The example is really simple and probably not so useful by itself but there are lot of uses I can imagine for the trail functions I will show in a few.

Using the Reactive Extensions make very simple to collect and manipulate the events coming from a source, like you are querying a database. The library itself define a number of methods that operate this way. The buffering functions for instance take a stream of events and collect them in groups based on count or timeout. BufferWithCount gives chunks of counted events and BufferWithTime collect the events generated in a specific timeout.  For example, given this sequence:

1,2,3,4,5,6,7,8,9

TrailWithCount(3) returns

1,2,3 - 4,5,6 - 7,8,9

In the following code I show an extension method that is able to collect the events creating a Trail based on count. I called it TrailWithCount; Given the previous collection the result will be

1,2,3 - 2,3,4 - 3,4,5 - 4,5,6 - etc...

   1: public static IObservable<IEnumerable<T>> TrailWithCount<T>(this IObservable<T> observable, int count)
   2: {
   3:     Queue<T> queue = new Queue<T>();
   4:  
   5:     return observable.Select(
   6:         o =>
   7:         {
   8:             queue.Enqueue(o);
   9:  
  10:             while (queue.Count > count) queue.Dequeue();
  11:             return queue.ToArray();
  12:         });
  13: }

This method take in input an IObservable<T> and returns an IObservable<IEnumerable<T>>. This is very close to the BufferWithCount method that returns an IObservable<IList<T>>. I preferred the use of IEnumerable<T> instead of IList<T> because I do not need the Insert and Remove methods of this interface. In the first row of the method I create a Queue<T>. It is important to remember that this collection will be created once the first time the method is called and thanks to the usage of lambda expression it will be alive and available to the body of the Select method for each event we get from the stream.

So, every time we get an event, in the Select method I add it to the Queue and then I remove the ones that exceed the count. Finally I select the items in the queue a result of the lambda expression so they are forwarded to the next extension method in the chain.

The same way, but taking advantage od the Timestamped<T> class I can operate to collect the trail events by time. The Timestamped<T> class is useful to add a timestamp (the moment when the event was received) to the item I add to the queue. So instead of removing items from the queue when they exceed a count I compare the timestamp with the current time and I remove the ones that are outside the defined timeout. Here is the method:

   1: public static IObservable<IEnumerable<T>> TrailWithTime<T>(this IObservable<T> observable, TimeSpan timeSpan)
   2: {
   3:     Queue<Timestamped<T>> queue = new Queue<Timestamped<T>>();
   4:  
   5:     return observable.Select(
   6:         o =>
   7:         {
   8:             DateTime now = DateTime.Now;
   9:  
  10:             queue.Enqueue(new Timestamped<T>(o, now));
  11:  
  12:             while (now - queue.Peek().Timestamp > timeSpan)
  13:                 queue.Dequeue();
  14:  
  15:             return queue.Select(v => v.Value).ToArray();
  16:         });
  17: }

Ok, now that we got the Trail method it is time to use them. To visualize the resulting trail I will catch the MouseMove events and collect the resulting points to draw the trail on the plugin area. So first of all I attach the MouseMove using the Observable.FromEvent then I transform the output events to a stream of Point calling GetPosition for every EventArgs. Finally I call the TrailWithCount (or TrailWithTime) method just before subscribing to the stream.

   1: Observable.FromEvent<MouseEventHandler, MouseEventArgs>(
   2:     ev => new MouseEventHandler(ev),
   3:     ev => this.LayoutRoot.MouseMove += ev,
   4:     ev => this.LayoutRoot.MouseMove -= ev)
   5:     .Select(o => o.EventArgs.GetPosition(this.LayoutRoot))
   6:     .TrailWithTime(TimeSpan.FromSeconds(3))
   7:     .Subscribe(DrawLine);

The Subscribe method will call a Draw method that simply assign the points of the trail to a Polyline. This will show a trail that grow to the required length then is shortened at the end when the mouse moves. Here you can try by yourself moving the mouse on the following instance of the plugin:

Get Microsoft Silverlight

In the attached code you can download you will find the methods I discussed above and an additional TrailWithTimeAndCount method that have an hybrid behavior that combines both the other methods. To make the download working you have to download the Reactive Extensions from Nuget and add a reference to them in the project.

Download: http://www.silverlightplayground.org/assets/sources/SLPG.Trailing.Silverlight.zip (17 KB)