XAML Playground
about XAML and other Amenities

Metro: Wire events to ICommand with a (not so simple) extension

2012-04-10T00:58:49+01:00 by codeblock

Looking to the new Metro style applications in Windows 8, I recently found that the easiness of Silverlight lost some points in the move to the new Metro application environment. One of the important things that are missed in XAML for Metro is the ability of wire events of the View to commands in the ViewModel. To be more precise, this capability exists but is limited to instances of ButtonBase class like Button and Hyperlinks. This scenario is known to Silverlight developers but it is easy worked around with Behaviors. Behaviors and Triggers comes from the Expression Blend SDK and are very useful. I think many of you know the EventToCommand class provided by the MVVM Light Toolkit that is able to wire commands to every kind of events.

Unfortunately behaviors are not supported in Metro applications (at least for the moment) so the sole way to handle events is to use codebehind to programmatically call commands of the ViewModel. For this reason I started to work hard to find a way to create a behavior's surrogate, and I finally achieved this result. Please take note that the solution I present here relies on two tricks made to work around some limitations I found. I hope these workarounds will not be required anymore in the future.

Create an infrastructure

As many know, Behaviors are based on Attached Properties. This useful feature still exists in XAML for Metro so it seems possible to replicate the behaviors writing some code. For the purpose of my goal, fully recreate the behaviors infrastructure is too difficult and takes too much time. So I decided to work striping out every kind of generalization and go straight to the minimal implementation.

In the solution attached to this post there are 6 classes that supports the behavior-style:

AttachableCollection: a special collection that can be attached to a DependencyObject. This instance is the element to which the binding is attached (an element of the Visual Tree)

DependencyObjectCollection: a generic collection able to host dependency objects. This collection is a DependencyObject itself.

Command: this class represents the binding of an event to a command. It is able to receive the name of the event, the binding to the command an to the command parameter. All the logic to connect the event to the command is hosted inside this class and its inner classes.

CommandCollection: AttachableCollection that contains the commands related to a single element of the visual tree

IAttachedObject: interface implemented by AttachableCollection and Command. It allows to connect the element source of events to the classes partecipating to the structure.

Extensions: static class used to expose the Attached Property

Thanks to these classes you will be able to write the following XAML:

   1: <Button Content="{Binding ButtonTitle}">
   2:     <xpg:Extensions.Commands>
   3:         <xpg:Command EventName="Click" Binding="{Binding ClickCommand}" ParameterBinding="{Binding ButtonTitle}" />
   4:         <xpg:Command EventName="Holding" Binding="{Binding HoldCommand}" ParameterBinding="{Binding ButtonTitle}" />
   5:     </xpg:Extensions.Commands>
   6: </Button>

Fully explaining the solution is hard. I invite you to explore the source codes I provide to understant the reasons behind every single class. The only thing you must have clear in mind is that most of the classes are made to propagate the instance of the source object along all the commands instances.

How it works

Part of the solution I've created starts from this post in codeproject. It describes a solution, based on attached properties, that enable to connect a single event to a command. Unfortunately this solution works only with the previous Developer Preview but it does not works with the latest Windows 8 Community Preview.

The reason is hard to understant to me, but it seems something in WinRT prevents to programmatically attach events. The following code results in an exception:

   1: if (eventInfo != null)
   2: {
   3:     Delegate handler = eventHooker.GetEventHandler(eventInfo);
   4:     eventInfo.AddEventHandler(d, handler);
   5: }

To work around to this problem I found a new class that seems to be created for this exact purpose. The class WindowsRuntimeMarshal contains a method named AddEventHandler that does the same. The documentation states this class is created to support the .NET Framework. But it is the only way to hook events as we need.

   1: if (eventInfo != null)
   2: {
   3:      Delegate handler = eventHooker.GetEventHandler(eventInfo);
   5:      WindowsRuntimeMarshal.AddEventHandler<Delegate>(
   6:          dlg => (EventRegistrationToken)eventInfo.AddMethod.Invoke(dependencyObject, new object[] { dlg }),
   7:          etr => eventInfo.RemoveMethod.Invoke(dependencyObject, new object[] { etr }), handler);
   8: }

After this the events are hooked up and the command need to be raised. This presents another problem. No matter if the base class is DependencyObject or FrameworkElement, there is not any way to get databinding to work as I expect. I need to deep investigate on this problem but for the moment I was able to get the Binding object and to evaluate it using a BindingEvaluator class. This is the main reason because I've not user Command and CommandParameter for the properties but instead I used Binding and ParameterBinding. Here is the code to read databinding:

   1: /// ... omissis
   3: private void OnEventRaised(object sender, object e)
   4: {
   5:      BindingEvaluator commandBinding = new BindingEvaluator((FrameworkElement)sender, this.Binding.Binding);
   6:      ICommand command = commandBinding.Value as ICommand;
   8:      object commandParameter;
  10:      if (this.Binding.ParameterBinding is Binding)
  11:      {
  12:          BindingEvaluator commandParameterBinding = new BindingEvaluator((FrameworkElement)sender, (Binding)this.Binding.ParameterBinding);
  13:          commandParameter = commandParameterBinding.Value;
  14:      }
  15:      else
  16:          commandParameter = this.Binding.Parameter;
  18:      if (command != null)
  19:          command.Execute(commandParameter);
  20: }
  22: /// ... omissis
  24: private sealed class BindingEvaluator : FrameworkElement
  25: {
  26:     /// <summary>
  27:     /// Instance of the binding to evaluate
  28:     /// </summary>
  29:     private Binding Binding { get; set; }
  31:     #region Value
  33:     /// <summary>
  34:     /// Exposes the Dependency Property related to the Value property
  35:     /// </summary>
  36:     public static readonly DependencyProperty ValueProperty =
  37:         DependencyProperty.Register("Value", typeof(object), typeof(BindingEvaluator), new PropertyMetadata(DependencyProperty.UnsetValue));
  39:     /// <summary>
  40:     /// Gests the value retrieved from the binding
  41:     /// </summary>
  42:     public object Value
  43:     {
  44:         get
  45:         {
  46:             return (object)GetValue(ValueProperty);
  47:         }
  48:         private set { SetValue(ValueProperty, value); }
  49:     }
  51:     #endregion
  53:     /// <summary>
  54:     /// Create an instance of the evaluator
  55:     /// </summary>
  56:     /// <param name="element">Instance of element to inherit data context</param>
  57:     /// <param name="binding">Instance of the binding to evaluate</param>
  58:     public BindingEvaluator(FrameworkElement element, Binding binding)
  59:     {
  60:         this.DataContext = element.DataContext;
  61:         this.Binding = binding;
  62:         SetBinding(BindingEvaluator.ValueProperty, this.Binding);
  63:     }
  64: } 


With these workarounds the solution now works. I'm using it in a project I'm working to develop usign MVVM Light Toolkit. It allows to easily connect Views to ViewModels without wasting codebehind with lot of event handlers. If you want I attached the code, side by side with an example. Please feel free to contact me for any issue or suggestion.

Download: http://www.silverlightplayground.org/assets/sources/XPG.Extensions.zip (396kb)

Download Silverlight & WP7 RFB Library

2012-03-07T00:34:58+01:00 by codeblock

Senza-titolo-1Today I decided to release the libraries I wrote to handle the VNC connection, implementing the Remote Framebuffer protocol, as an Open Source project under the Creative Common license. You can download the library from this page:


During last weeks I've published a new version of SilverVNC, my popular client for Remote Framebuffer connections, that works on Windows Phone 7.5. After publishing the software as Open Source project on codeplex, for Silverlight 3.0 only, now the marketplace has also a mobile version that you can download for free or buy at these addresses:

Free Edition: view only

Standard Edition: full control

Enjoy the library.

Take a screenshot with Silverlight 5.0 and pInvoke

2012-02-28T00:36:14+01:00 by codeblock

PInvoke is a new entry in Silverlight 5.0 runtime. For the one that are not aware of what is pInvoke I will say it stands for "Platform Invoke". It is a set of classess and attributes that allows the Silverlight runtime to access the low-level Win32 API of Windows Operating System.

After Silverlight 4.0 brought COM interop in Silverlight, the team decided to accomplish the last step and integrate also pInvoke. As you understand, it is only restricted to Windows OS, but is some scenario it may be a very useful thing to cross the subtle line from "can't do" to "can do". Wether you have to detect USB keys, interact with devices and so on, pInvoke require you to directly access the API preparing the mapping to the OS funzions and handling unmanaged resources.

As a littel sample I ported an old example to Silverlight. The code below implements a simple funzion that is able to take a screenshot of the desktop.

   1: public static class ScreenCapture
   2: {       
   3:   public static WriteableBitmap GetDesktopImage()
   4:   {
   5:       WriteableBitmap bmap = null;
   7:       // initialize unmanager pointers
   8:       IntPtr hDC = IntPtr.Zero,
   9:              hMemDC = IntPtr.Zero,
  10:              desktop = IntPtr.Zero;
  12:       try
  13:       {
  14:           // get a reference to desktop
  15:           desktop = User32.GetDesktopWindow();
  16:           // get an handle to Device Context
  17:           hDC = User32.GetDC(desktop);
  18:           // create a new Device Context in memory
  19:           hMemDC = Gdi32.CreateCompatibleDC(hDC);
  21:           // read size of desktop window
  22:           Size size = new Size
  23:           {
  24:               Width = User32.GetSystemMetrics(Gdi32.SM_CXSCREEN),
  25:               Height = User32.GetSystemMetrics(Gdi32.SM_CYSCREEN)
  26:           };
  28:           // create a bitmap compatible with desktop
  29:           IntPtr hBitmap = Gdi32.CreateCompatibleBitmap(hDC, size.Width, size.Height);
  31:           if (hBitmap != IntPtr.Zero)
  32:           {
  33:               // select memory Device Context into the new bitmap
  34:               IntPtr hOld = (IntPtr)Gdi32.SelectObject(hMemDC, hBitmap);
  36:               // copy the desktop to the memory handle
  37:               Gdi32.BitBlt(hMemDC, 0, 0, size.Width, size.Height, hDC, 0, 0, (int)TernaryRasterOperations.SRCCOPY);
  39:               // select the memory Device Context into the bitmap
  40:               Gdi32.SelectObject(hMemDC, hOld);
  42:               // initialize a bitmap info
  43:               BitmapInfo bi = new BitmapInfo 
  44:               { 
  45:                   biSize = Marshal.SizeOf(typeof (BitmapInfo)), 
  46:                   biWidth = size.Width, 
  47:                   biHeight = size.Height, 
  48:                   biPlanes = 1, 
  49:                   biBitCount = 32, 
  50:                   biCompression = 0, 
  51:                   biSizeImage = 0, 
  52:                   biXPelsPerMeter = 0, 
  53:                   biYPelsPerMeter = 0, 
  54:                   biClrUsed = 0, 
  55:                   biClrImportant = 0 
  56:               };
  58:               // calculate byte size of the area
  59:               int dwBmpSize = ((size.Width * bi.biBitCount + 31) / 32) * 4 * size.Height;
  60:               byte[] data = new byte[dwBmpSize];
  62:               // initialize a WriteableBitmap to output the result
  63:               bmap = new WriteableBitmap(size.Width, size.Height);
  65:               // copy bitmap to byte array
  66:               Gdi32.GetDIBits(hMemDC, hBitmap, 0, (uint)size.Height, data, ref bi, 0);
  68:               // compy byte array to WriteableBitmap
  69:               for (int i = 0; i < data.Length; i += 4)
  70:               {
  71:                   int y = size.Height - ((i / 4) / size.Width) - 1;
  72:                   int x = (i / 4) % size.Width;
  73:                   int pixel = data[i + 0] | (data[i + 1] << 8) | (data[i + 2] << 16) | (data[i + 3] << 24);
  74:                   bmap.Pixels[y * size.Width + x] = pixel;
  75:               }
  76:           }
  77:       }
  78:       finally
  79:       {
  80:           // release unmanaged resources
  81:           if (hMemDC != IntPtr.Zero)
  82:               Gdi32.DeleteDC(hMemDC);
  83:           if (hDC != IntPtr.Zero)
  84:               User32.ReleaseDC(desktop, hDC);
  85:       }
  87:       // return bitmap
  88:       return bmap;
  89:   }
  90: }

I wrote a number of comments inside the code example to try explain how it works, but in a few words it create a buffer in memory, take a reference to the desktop and copies it to the new area. Then finally it copy again the buffer to a byte array to allow managed code to access the captured image. It is copied to a WriteableBitmap and then returned to the caller.

To use the class you can simply call the static method and check for the result value and exceptions. The code automatically handles the unmanaged resources and is done to freed them before to exit.

   1: private void Button_Click(object sender, RoutedEventArgs e)
   2: {
   3:     Application.Current.MainWindow.Hide();
   5:     Delay(1000,
   6:           () =>
   7:           {
   8:               try
   9:               {
  10:                   BitmapSource source = ScreenCapture.GetDesktopImage();
  12:                   if (source != null)
  13:                       screenshot.Source = source;
  14:                   else
  15:                       MessageBox.Show("Impossibile completare la cattura!");
  16:               }
  17:               catch (Exception ex)
  18:               {
  19:                   MessageBox.Show(ex.Message);
  20:               }
  21:               finally
  22:               {
  23:                   Application.Current.MainWindow.Show();
  24:                   Application.Current.MainWindow.Activate();
  25:               }
  26:           });
  27: }
  29: private void Delay(int timeout, Action action)
  30: {
  31:     Task task = new Task(
  32:         () =>
  33:         {
  34:             Thread.Sleep(timeout);
  36:             Deployment.Current.Dispatcher.BeginInvoke(action);
  37:         });
  39:     task.Start();
  40: }

This code minimizes the main window and then take a screenshot. Finally it reactivate the window and take it to the front. To compile this code you have to import a number of structures. The attached sample includes all the needed classes.

Download: XPG.PInvoke.zip

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

Reliable themes: Plan for fonts

2012-02-24T00:12:56+01:00 by codeblock

After you completes the first steps in creating your reliable theme, it is now time to move forward and consider another aspect in this task. When the palette is ready the next step in to plan for the typefaces. Fonts are a crucial aspect tha shares with colors the scene almost with the same weight.

Choosing the wrong typeface means make your application difficult to read so the user can be tired after a short usage, but this is only one aspect of the problem. Togheter with colors, fonts contribute to the general feel about the reliability and effectiveness of the user interface. It is really important to carefully choose a wide set of options about fonts

aspect of the typeface: it exists a huge number of typefaces and every one of them can be used in specific context. Carefully evaluate your font, preferring sans-serif on serif because the first one are more readable in different sizes when used in user interfaces.

size of the font: size matters, and it is not a joke. Size is not only a problem of readability but also a problem of space. you have to choose the right size balancing the readability and the space available for your content. Also you have to consider that big does not means automatically easy to read. Using an huge typeface can significantly reduce the number of words you can write in a row and force the user to move from left to right too much times.

significance and uniformity of the size: the size is also a problem of meaning. Using a big font makes the content really preminent over another part where you use a smaller typeface. An also you have to use an omogeneous size across different parts of the application. As an example if you decide to use a given size for the grid header you have to use the same size on all the grids of the application.

careful use font weight: font weight and italic can give an additional gear to your interface but as usual, abusing in bold and italics can make the interface confused and not readable. For this topic it is valid the same rule of the previous point. Choose a weight and style for each meaning and the use it omogeneously across all the elements.

contrast of font on background: color of the typeface can affect readability more than size. Always use an high contrast between the foreground and background but not the maximum. Using too high contrast can create flickering effect and reduce readability.

After choosing typeface, size, weight and the other parameters I discussed in the previous paragraphs, it is time to embed them in your theme. Here is a short set of easy rules:

#1 - Plan the fonts matrix

Given that you only use a unique typeface for your application, or that you plan for a single typeface at a time, the font used in your theme can be easily organized using a matrix. Your fonts matrix have the weight in the rows and the sizes in the columns. Here is a simple matrix:

  10pt 12pt 14pt 18pt 24pt 32pt 48pt
semilight side notes            
normal   textbox content   grid headers      
semibold       titles    
bold   input labels          

The font matrix really can help to better understand fonts across the parts of your application. You know that the upper left corner identifies parts that are less important than the lower bottom cell. You do not have to fill every cell in the matrix, but on the contrary the better is leaving the most of the cells empty.

#2 - Name your weights and sizes

Then, as we have done with colors, it is important to abstract names for weights and sizes. Primarily for sizes but also for weights you have to use a naming convention that remove the need of knowing the number or the real weight of the typeface. For weights you can user terms like "Light", "SemiLight", "Normal", "SemiBold", "Bold". You can alternatively use FontWeight or FontFace to determine weight. Lot of fonts are created in various flavors with a face for every weight. Segoe UI is an example.

   1: <FontFamily x:Key="FontFamilyLight">Segoe UI Light</FontFamily>
   2: <FontFamily x:Key="FontFamilySemiLight">Segoe UI SemiLight</FontFamily>
   3: <FontFamily x:Key="FontFamilyNormal">Segoe UI</FontFamily>
   4: <FontFamily x:Key="FontFamilySemiBold">Segoe UI SemiBold</FontFamily>
   5: <FontFamily x:Key="FontFamilyBold">Segoe UI Bold</FontFamily>

For sizes I usually use "ExtraSmall", "Small", "Normal", "Medium", "Large", "ExtraLarge", etc... This naming helps to separate the real size from the meaning of the size. You can assign to Normal a size of 12 or 18 and then recalculate all the other sizes on the base of the middle value. It is not important the regularity of the distribution but most of the times the distance between the intervals increase on the growing of the size.

   1: <mscor:Double x:Key="FontSizeTiny">9.33</mscor:Double>
   2: <mscor:Double x:Key="FontSizeExtraExtraSmall">10.667</mscor:Double>
   3: <mscor:Double x:Key="FontSizeExtraSmall">12</mscor:Double>
   4: <mscor:Double x:Key="FontSizeSmall">13.333</mscor:Double>
   5: <mscor:Double x:Key="FontSizeNormal">14.667</mscor:Double>
   6: <mscor:Double x:Key="FontSizeMedium">18.667</mscor:Double>
   7: <mscor:Double x:Key="FontSizeMediumLarge">21.333</mscor:Double>
   8: <mscor:Double x:Key="FontSizeLarge">24</mscor:Double>
   9: <mscor:Double x:Key="FontSizeExtraLarge">29.333</mscor:Double>
  10: <mscor:Double x:Key="FontSizeExtraExtraLarge">37.333</mscor:Double>
  11: <mscor:Double x:Key="FontSizeHuge">42.667</mscor:Double>

Remember that if you decide to use FontWeight for name the weight of the your application you have then to name your face:

   1: <!-- WEIGHTS -->
   2: <FontWeight x:Key="FontWeightLight">Thin</FontWeight>
   3: <FontWeight x:Key="FontWeightSemiLight">Light</FontWeight>
   4: <FontWeight x:Key="FontWeightNormal">Normal</FontWeight>
   5: <FontWeight x:Key="FontWeightSemiBold">Bold</FontWeight>
   6: <FontWeight x:Key="FontWeightBold">Black</FontWeight>
   8: <!-- FACE -->
   9: <FontFamily x:Key="FontFamilyDefault">Segoe UI</FontFamily>

#3 - Name your styles

As you should never use your colors directly in the markup, you should never use font family, weight and size in the same way. For fonts the problem is slightly more complicated because there is not a "Brush" instance to define to wrap the typeface. You have then to define a style for every control that have to use the typeface.

This may seems difficult but you have to keep in mind that, soon or later you will have to create a style for each element you have to put in the markup. So it is normal to assign the right typeface, weight and size combination to each one.

The most obvious element you have to create a style is TextBlock. And for textblocks you can use a conventional naming that identifies the parts where you have to put the text. To be more clear, the style you apply to textblock is the one you wrote in the cell of the font matrix.

<Style x:Key="TextInputLabelStyle" TargetType="TextBlock">
<Setter Property="FontFamily" Value="{StaticResource FontFamilyBold}" />
<Setter Property="FontSize" Value="{StaticResource FontSizeNormal}" />

Also remember to determine the default aspect of the TextBlock using implicit styles

<Style TargetType="TextBlock" BasedOn="{StaticResource TextInputLabelStyle}" />

After this your fonts have been strongly organized in your theme and you can start using blend to edit styles and templates. Blend UI is able to show your planned fonts easily and you can take advantage of naming to make the look & feel more effective.

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

Draw your Paths with Logo Turtle Graphics

2012-02-20T22:58:55+01:00 by codeblock

Working on a presentation I'm preparing about Silverlight 5.0, I wrote a funny example to demonstrate the new "Vector Printing" feature. My purpose was to put together a bunch of lines to send to the printer, but I was unsatisfied by any result I created by hand.

So, all of a sudden, I remembered the beauty of some figures, I drawed long time ago (perhaps I was 15), using the Logo Turtle Graphics principles and decided to write some code to draw them again. The result is funny. Try yourself to move the sliders in the following application to see the figures.

The code behind the example is really simple. I wrote a basic Turtle class that is able to manage the position of the turtle. It exposes a basic set of methods that emulates the movements that are tipical of a Logo procedure. Forward, Backward, Left and Right and so on.

   1: public class Turtle
   2: {
   3:     // Collection of geometries to draw the figure
   4:     private GeometryGroup Geometries { get; set; }
   5:     // current angle of the turtle
   6:     public double Angle { get; private set; }
   7:     // current position of the turtle
   8:     public Point Position { get; private set; }
   9:     // position of the pen
  10:     public bool IsPenDown { get; private set; }
  12:     /// <summary>
  13:     /// Inizializza una nuova istanza della classe <see cref="Turtle"/>.
  14:     /// </summary>
  15:     public Turtle(Path path)
  16:     {
  17:         this.Geometries = new GeometryGroup();
  18:         path.Data = this.Geometries;
  19:         this.Angle = 0.0;
  20:         this.Position = new Point(0, 0);
  21:         this.IsPenDown = true;
  22:     }
  24:     // lift up the pen
  25:     public void PenUp()
  26:     {
  27:         this.IsPenDown = false;
  28:     }
  30:     // lower the pen
  31:     public void PenDown()
  32:     {
  33:         this.IsPenDown = true;
  34:     }
  36:     // move forward
  37:     public void Forward(double size)
  38:     {
  39:         this.Move(size);
  40:     }
  42:     //  move backward
  43:     public void Backward(double size)
  44:     {
  45:         this.Move(-size);
  46:     }
  48:     // rotate to the left
  49:     public void Left(double angle)
  50:     {
  51:         this.Angle += ToRadians(angle);
  52:     }
  54:     // rotate to the right
  55:     public void Right(double angle)
  56:     {
  57:         this.Angle -= ToRadians(angle);
  58:     }
  60:     // move the pen of the specified size
  61:     private void Move(double size)
  62:     {
  63:         Point past = this.Position;
  65:         this.Position =
  66:             new Point(
  67:                 past.X + Math.Sin(this.Angle) * size,
  68:                 past.Y + Math.Cos(this.Angle) * size);
  70:         if (IsPenDown)
  71:         {
  72:             this.Geometries.Children.Add(
  73:                 new LineGeometry
  74:                 {
  75:                     StartPoint = past,
  76:                     EndPoint = this.Position,
  77:                 });
  78:         }
  79:     }
  81:     // convert degrees to radians
  82:     public double ToRadians(double angle)
  83:     {
  84:         return angle * Math.PI / 180.0;
  85:     }
  86: }

Then a short C# function does the rest and draws the figure on the basis of a simple mathematical algorithm. It simply repeat a poligon a number of times, rotating the origin point of a short amount of degrees. The sliders change the number of sides of the poligon and the amount of the rotation expressed in fraction of 360°.

   1: private void Draw(Path pathToDraw)
   2: {
   3:     int sides = (int)this.SidesSlider.Value;
   4:     double corner = 360 / (double)sides;
   5:     int repeat = (int)this.RepeatSlider.Value;
   6:     double angle = 360 / (double)repeat;
   8:     Turtle turtle = new Turtle(pathToDraw);
  10:     for (int j = 0; j < repeat; j++)
  11:     {
  12:         for (int i = 0; i < sides; i++)
  13:         {
  14:             turtle.Forward(50);
  15:             turtle.Left(corner);
  16:         }
  18:         turtle.Right(angle);
  19:     }
  20: }

I'm always impressed by the beauty of the simple mathematical drawing. The prints I got from this example have been forwarded to my daughter and some hours after they are completely coloured and becomed a beautiful picture for the door of our refrigerator. I hope you like this funny Vector Printing example.

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

Reliable Themes: Plan for colors

2012-02-17T00:59:44+01:00 by codeblock

Working on applications built with Silverlight, it is really common you have to deal with styles, templates, and often this means you have to build a theme pervading an entire application. Building a theme is not so simple as you may believe at the first sight. It requires instead a careful planning, from the conceptual side first and in the technical implementation then. There are lot of topics regarding the creation of a theme from the designer point of view but here I want to discuss about the implementation details that are often underestimated.

Styles are a great thing. But if you ever tried to use them without a careful planning you are aware that, more than often, they become a nightmare. We all are conscious about the reasons that move us to adopt styles in an application, but when the time comes we all tent to forget these reasons. And this is the mother of all the mistakes - ok, not only about styles - that usually makes our "stylesheet" more similar to a disordered trashcan instead of an useful thing. You start coding UI, then you understand that some properties have the same values, so you extract them and put it into a style. This may seems good but soon (or perhaps too late) you start to be unable to reuse the same style on more than two or three controls before you need to duplicate it.

Planning for styles is a difficult game, but it may change your life to the better if you know where to start from. And in my humble opinion the real start point - just after the end of the designer's work - is to create a palette. Colors and Brushes are usually the most obvious properties you move to a style, but having your colors spread over a 5 thousand rows stylesheet is almost not useful as if it was spread along all the pages. So, before you start, write down this sentence and put it on top of your monitor: "I will never write a color manually more than once".

#1 - Name your colors

It may seems silly but this rule automatically imply we have to name our colors. Ok guy, please stop writing now. Do not name Red as Red. Instead you have to use a more meaningful naming that adhere to the matter of your application. I usually make large use of adjectives like "Light" and "Dark". The reason to not name Red as Red (this is about to become another sentence to put on your monitor) it that easily, what it is Red now may become Green tomorrow and you for sure do not want to name as Red all your Green :) If a theme make its work fine it allows you to easily change lot of your UI without changing anything in the pages. So, here is a simple example of a named palette:

   1: <Color x:Key="ExtraDarkColor">#FF333333</Color>
   2: <Color x:Key="DarkColor">#FF666666</Color>
   3: <Color x:Key="BasicColor">#FF888888</Color>
   4: <Color x:Key="LightColor">#FFdddddd</Color>
   5: <Color x:Key="ExtraLightColor">#FFeeeeee</Color>

This is a very simple example but it explains the point effectively. You have to choose your names basing more on where or when they are used instead of the color they represent. It is a good rule of thumb to have a scale of light fore each color you use in your palette. This makes your life easy when you need to present selections, embossed borders (really? please avoid emboss your borders) and so on. This section has to be written at the very start of a ResourceDictionary (in another post I will explain how to organize the dictionaries) and it is the sole point where a color appears in the one I call the "sharped form" (remember the "#" in front of the color? ok you got the sharp).

#2 - Name your brushes

Ok, I'm reading clear on you the doubt. What the hell I can do with a bunch of colors? You all are right, colors are a form that is not ready to be used in your markup. 9 times over 10 a property of an element does not accept an instance of Color but instead it requires a Brush. So, as you did with colors, now you have to name your brushes. Brush names are more close to the real usage, and please keep in mind that nothing prevent you from use the same color in two or more brushes. Here is a set of brushes:

   1: <SolidColorBrush x:Key="BackgroundBrush" Color="{StaticResource ExtraLightColor}" />
   2: <SolidColorBrush x:Key="HighlightBrush" Color="{StaticResource LightColor}" />
   3: <SolidColorBrush x:Key="SelectionBrush" Color="{StaticResource LightColor}" />
   4: <SolidColorBrush x:Key="AlertBrush" Color="{StaticResource DarkColor}" />

As you can see, the brushes' name suggests the use you have to do with it. In this example you have Highlights and Selections rendered with the same LightColor and the AlertBrush is a DarkColor. This one is a good example of the naming: you do not need to have the Alert as Red, you only have to use a color that stands over the BackgroundColor. An the naming here helps you to remember the meaning instead of it color.

#3 - Name your gradients

Some applications make use of gradients. As you know gradients are simply a transition between a series of colors. And with your named colors you can for sure create a set of named gradients. Thanks to the Brush concept you can avoid to put gradients in the markup but you can easily put them side by side with the palette and the solid brushes and this way you are able in the future to change a solidcolor to a gradient and a gradient to a solidcolor:

   1: <LinearGradientBrush x:Key="SoftBrush" EndPoint="0.5,1" StartPoint="0.5,0">
   2:     <GradientStop Offset="0.0" Color="{StaticResource ExtraLightColor}" />
   3:     <GradientStop Offset="1.0" Color="{StaticResource LightColor}" />
   4: </LinearGradientBrush>
   6: <LinearGradientBrush x:Key="ToolbarBrush" EndPoint="0.5,1" StartPoint="0.5,0">
   7:     <GradientStop Offset="0.0" Color="{StaticResource DarkColor}" />
   8:     <GradientStop Offset="1.0" Color="{StaticResource BasicColor}" />
   9: </LinearGradientBrush>

In my old applications I was use to call gradients as a named followed by "Gradient" but recently I've understand that it is a bad policy like naming Red as Red. You will understand it the first time you whant to flat your embossed toolbar and you transform a gradient to a solid brush.

#4 - Take advantage of Blend (with care)

imageOnce you have created a palette and a set of brushes you can start using them and Expression Blend is your best friend but you have to pay attention to something.

On the right side you see the color tool of Blend. Instead of it you see a tab named "Color Resources". Please always remember to never use it. This tab exposes the Color instances you named in your palette. At the first sight is may seems a good idea to select colors from here but is means you put a Brush in the markup and this brush wraps the color you have selected.

Just because Colors are not directly supported, Blend expose them to let you edit gradients easily but it wraps them into a brush before to set the property of the element you are editing. You have instead to use the last button on the very top of the window. It is named "Brush Resources" and it shows the brushes you have laboriously defined.

It is all about colors

As I've already said, your palette is the central point of the theme of your application. And planning themes carefully let you change the look & feel easily making its lifetime much more longer. XAML Resources are ten times more powerful than CSS and the content of this post is a good example of this power. As an interesting excercise, please try to reproduce the matter of this post in a CSS and you will understand that it is simply impossible.

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

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:\";
   5:     public IEnumerable<FileSystemItem> GetItems(string path)
   6:     {
   7:         List<FileSystemItem> items = new List<FileSystemItem>();
   9:         DirectoryInfo directory = new DirectoryInfo(Root + path);
  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:         }
  25:         foreach (var item in directory.GetFiles())
  26:         {
  27:             items.Add(new File
  28:             {
  29:                 Name = item.Name,
  30:                 Size = item.Length
  31:             });
  32:         }
  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: { }
   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; }
   5:     public MainPageViewModel()
   6:     {
   7:         this.Items = new ObservableCollection<ViewModelBase>();
   8:         this.Load();
   9:     }
  11:     private void Load()
  12:     {
  13:         FileSystemServiceClient client = new FileSystemServiceClient();
  14:         client.GetItemsCompleted += new EventHandler<GetItemsCompletedEventArgs>(client_GetItemsCompleted);
  15:         client.GetItemsAsync(string.Empty);
  16:     }
  18:     private void client_GetItemsCompleted(object sender, GetItemsCompletedEventArgs e)
  19:     {
  20:         this.Items.Clear();
  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:     }
  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:     }
  23:     private void client_GetItemsCompleted(object sender, GetItemsCompletedEventArgs e)
  24:     {
  25:         this.Items.Clear();
  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:         }
  35:         this.IsExpanded = true;
  36:     }
  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>
   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>
  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>
  24: </Grid.Resources>
  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;
   3: Stack<Cell> stack = new Stack<Cell>();
   4: this.Reset();
   6: Cell cell = this.GetRandom(0);
   7: cell.Type = CellType.Enter;
   8: cell.Visited = true;
  10: while (true)
  11: {
  12:     Cell adiacent = this.GetAdiacentNonVisited(cell);
  14:     if (adiacent != null)
  15:     {
  16:         stack.Push(cell);
  17:         adiacent.Visited = true;
  18:         cell = adiacent;
  20:         progress++;
  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: }
  33: cell = this.GetRandom(this.Height - 1);
  34: cell.Type = CellType.Exit;
  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>();
   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);
  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);
  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));
  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));
  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));
  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));
  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));
  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);
   4: IEnumerable<VertexPositionColor> edges = renderer.Render(this.Maze);
   6: this.Buffer = new VertexBuffer(
   7:     GraphicsDeviceManager.Current.GraphicsDevice,
   8:     VertexPositionColor.VertexDeclaration,
   9:     edges.Count(),
  10:     BufferUsage.WriteOnly);
  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);
  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;
   6:     Cell cell = this.Maze.CellAt(
   7:         (int)(this.Maze.Width * e.Position.X),
   8:         (int)(this.Maze.Height * e.Position.Y));
  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);
  16:     e.Cancel = false;
  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);
   5:     SocketAsyncEventArgs arguments = new SocketAsyncEventArgs();
   6:     arguments.RemoteEndPoint = new DnsEndPoint(Application.Current.Host.Source.DnsSafeHost, 4530);
   8:     var socketAsObservable = from args in Observable.FromEvent<SocketAsyncEventArgs>(
   9:                                  ev => arguments.Completed += ev,
  10:                                  ev => arguments.Completed -= ev)
  11:                              select args.EventArgs;
  13:     socketAsObservable
  14:         .Where(args => args.LastOperation == SocketAsyncOperation.Connect)
  15:         .Subscribe(
  16:         args =>
  17:         {
  18:             args.Dispose();
  19:             this.Receive();
  20:         });
  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);
   6:     var socketAsObservable = from args in Observable.FromEvent<SocketAsyncEventArgs>(
   7:                                  ev => arguments.Completed += ev,
   8:                                  ev => arguments.Completed -= ev)
   9:                              select args.EventArgs;
  11:     socketAsObservable
  12:         .Where(args => args.LastOperation == SocketAsyncOperation.Receive)
  13:         .Throttle(TimeSpan.FromMilliseconds(500))
  14:         .ObserveOnDispatcher()
  15:         .Subscribe(OnReceive);
  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);
   5:     IEnumerable<Sample> samples = this.GetSamples(ref data);
   7:     Array.Clear(args.Buffer, 0, 1024);
   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);
  18:     if (this.Socket.Connected)
  19:         this.Socket.ReceiveAsync(args);
  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();
   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();
  14:         Console.WriteLine("Service is listening on {0} port {1}.", IPAddress.Loopback, 4530);
  15:         Console.WriteLine("Press enter to stop");
  17:         Func<IObservable<TcpClient>> accept =
  18:             Observable.FromAsyncPattern<TcpClient>(listener.BeginAcceptTcpClient, listener.EndAcceptTcpClient);
  20:         accept()
  21:             .Where(o => o.Connected)
  22:             .ObserveOn(Scheduler.NewThread)
  23:             .Subscribe(acceptedClient => OnAccept(acceptedClient, accept));
  25:         Console.ReadLine();
  26:         cts.Cancel();
  27:     }
  28: }

In the first lines the server binds to the port 4530 of the localhost ip ( 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));
   8:     Console.WriteLine("channel opened");
  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:     }
  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");
   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();
  12:     NativeMethods.MEMORYSTATUSEX memStatus = new NativeMethods.MEMORYSTATUSEX();
  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:     }
  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 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.