XAML Playground
about XAML and other Amenities

#wp8tip: Adapt images to different resolutions

2013-04-23T23:32:03+01:00 by Andrea Boschin

Windows Phone 8 comes with the support of multiple resolutions, that must be supported by new applications to cover all the available devices. As you can understand, it is really important to be able to support these new resolutions seamless, but it may be annoying when we have to deal with a number of images. Indeed, if vector graphics scales directly to all the resolutions, at the sole price of correctly design yout layout, with images you are forced to provide a different size to every resolution, if you want the best result.

To make my life easy, I wrote a simple attached property that enable me to easily specify the path of the image and have it updated with a resolution suffix. It is something similar to which it happens automatically in Windows 8. First of all a mini helper to convert an uri and add the resolution switch the path:

   1: public static class ResolutionHelper
   2:  {
   3:      public static Uri ToCurrentResolution(this Uri uri)
   4:      {
   5:          string uriString = uri.OriginalString;
   6:  
   7:          if (uriString.EndsWith(".jpg") || uriString.EndsWith(".jpeg") || uriString.EndsWith(".png"))
   8:          {
   9:              int dot = uriString.LastIndexOf('.');
  10:              uriString = uriString.Substring(0, dot) + "." + ResolutionHelper.CurrentResolutionString + uriString.Substring(dot, uriString.Length - dot);
  11:              return new Uri(uriString, UriKind.RelativeOrAbsolute);
  12:          }
  13:  
  14:          return uri;
  15:      }
  16:  
  17:      private static string CurrentResolutionString
  18:      {
  19:          get
  20:          {
  21:              if (App.Current.Host.Content.ScaleFactor == 100)
  22:                  return "screen-wvga";
  23:              else if (App.Current.Host.Content.ScaleFactor == 160)
  24:                  return "screen-wxga";
  25:              else if (App.Current.Host.Content.ScaleFactor == 150)
  26:                  return "screen-720p";
  27:              else
  28:                  throw new InvalidOperationException("Unknown resolution");
  29:          }
  30:      }
  31:  }

Once I have this tool class ready, it's easy to imagine to specify an uri to the image source and have it converted on the basis of the current resolution. I've tried a number of solutions but I finally found that writing a simple Attached property is the most simple and effective. Here is the extension:

   1: public class AutoScale : DependencyObject
   2: {
   3:     public static readonly DependencyProperty SourceProperty =
   4:         DependencyProperty.RegisterAttached("Source", typeof(Uri), typeof(Image), new PropertyMetadata(null));
   5:  
   6:     public static Uri GetSource(DependencyObject obj)
   7:     {
   8:         return (Uri)obj.GetValue(SourceProperty);
   9:     }
  10:  
  11:     public static void SetSource(DependencyObject obj, Uri value)
  12:     {
  13:         obj.SetValue(SourceProperty, value);
  14:  
  15:         Image image = obj as Image;
  16:  
  17:         if (image != null)
  18:         {
  19:             image.Source = new BitmapImage(value.ToCurrentResolution());
  20:         }
  21:     }
  22: }

The attached property has the advantage of making the trick seamless. Instead of writing the Source property in the XAML, I write tha "local.AutoScale.Source" property and is automatially update the underlying image:

   1: <Image local:AutoScale.Source="/Assets/Images/img.jpg" 
   2:        HorizontalAlignment="Center" 
   3:        VerticalAlignment="Center" Width="300" Height="300"/>

Tip: a common error with Dependency Property metadata

2013-01-22T23:54:03+01:00 by Andrea Boschin

Recently someone pointed me to a malfunction on one of my examples. He sent me a repro project and, after I've run the example, I found the problem as he described it to me. But it took me a long time to figure out the reason. The problem was really simple: an instance of a templated control in a page seems to share a property with another instance of the same control in another page... This sounds impossible at first sight but if the property is a Dependency Property the issue is real. Here is the original code:

   1: public static readonly DependencyProperty ParallacticLayersProperty =
   2:     DependencyProperty.Register(
   3:         "ParallacticLayers", 
   4:         typeof(List<FrameworkElement>), 
   5:         typeof(ParallacticGridView), new PropertyMetadata(new List<FrameworkElement>()));

The code above may appear correct but it has an important issue. When a dependency property is used with a collection type, it is important to not initiate the metadata inline with the declaration, because the declaration of a static property only create a single instance that is shared by all the controls that use thid property. The correct example is the following:

   1: public static readonly DependencyProperty ParallacticLayersProperty =
   2:     DependencyProperty.Register(
   3:         "ParallacticLayers", 
   4:         typeof(List<FrameworkElement>), 
   5:         typeof(ParallacticGridView), new PropertyMetadata(null));

The collection datatypes only, make this problem evident, because once the property has been initialized it does not change the value. The observed behavior shows that the collection always adds the items without removing them. This apply to every XAML dialect...

Customized semantic zoom: an alternative to common grouping

2013-01-18T01:36:55+01:00 by Andrea Boschin

A really distinctive aspect of the Windows Store apps is a completely new way of displaying information, that not only suggest a very simplified design able to improve the importance of content, but also introduces new paradigms to make easy to browse the structure of the information. So they born a number of controls that supports scrolling beyond the size of the screen, that display elements of the right dimension for the fingers, that easily enable grouping to make simple to reach what the user needs. The cutting edge of this completely new interface if for seru the semantic zoom control that adds a thrid dimension to the browsing of data enabling a flawless navigation over grouped information.

The pinch and zoom gesture is becoming a common habit while using a Windows Store app but unfortunately the developers have always used this control as-is, without experimenting other ways of use the Semantic Zoom views. What people always forget is that the Semantic Zoom control is easily extensible and, with a low effort it is possible to create controls that shows customized views for one of the zoom levels or both.

During the development of the my app "EarthQuake Alerts" I've tried to overcome the now common groups/items way of using this control creating a map for the zoomed-out view. In the figure below you can see the two view of the main screen of the app.

screenshot_01172013_000205 screenshot_01172013_000210

As you can see while the zoomed-in view is a common GridView displaying grouped items, the zoomed out view shows a map with a number of flags. To understand the meaning of the flags you are to be aware that each flags belogs to a group in the SemanticZoom zoomed in. The position of the flag is calculated as the medium point between all the coordinates belonging to a group.

Implementing the ISemanticZoomInformation

If you explore the documentation of the two controls that currently can be used as part of a semantic zoom view you can see that both the GridView and ListView implement the ISemanticZoomInformation. Infact this interface is directly used by the SemanticZoom control to send and receive information about the interaction of the user to change the visual state. So from a point of view a control can notify about the selection of an item and the SemantiZoom acts changing the view from one to the other pointing the focus to the selected group or item. On the other side the SemanticZoom can ask the target to focus an item or notify when a change starts or ends. The interface contains a number of methods and properties. Here you can view the complete documentation on MSDN: http://slpg.org/VavDrp

In my case the implementation was very simple because the target map does not need to complex interactions like focusing an element. This is because the map extends to the whole screen and the focus is not really useful .The sole interaction I need to handle is the click on a flag that have to switch to the secondary view. To get this working I used the SemanticZoomOwner property. This property give a reference to the SemanticZoom that contains the control. So every time I receive the click of an item I call the following method:

   1: private void ApplySemanticZoom(IGeographicGroup<IGeographicPoint> item)
   2: {
   3:     this.CurrentItem = item;
   4:     this.SemanticZoomOwner.ToggleActiveView();
   5: }

This simple call is able to switch from the current mode (the map in ZoomedOut) an the detail (the ZoomedIn). After the switch has started you have to take care of some other aspects. These are implemenetd overriding some other simple methods:

   1: public void StartViewChangeFrom(SemanticZoomLocation source, SemanticZoomLocation destination)
   2: {
   3:     source.Item = this.CurrentItem;
   4:     destination.Item = this.CurrentItem;
   5: }
   6:  
   7: public void StartViewChangeTo(SemanticZoomLocation source, SemanticZoomLocation destination)
   8: {
   9:     destination.Item = source.Item;
  10: }

The first override is called when the control has started the swith from itself to the alternative view. In this method I set the Destination as the selected item. In the other method, when the control is called I simply set the destination as the source. Remember that the CurrentItem property contanis the element clicked.

Really it is all what you need to do. Given the very few documentaion on the internet I spend some hours to understand the point. But after I understand the meaning of every method the implementation has become easy like a breeze.

Windows 8 apps: Make your GridView parallactic

2012-10-24T00:46:33+01:00 by Andrea Boschin

Few months ago I wrote a post about a way to apply a parallactic effect to a GridView. Given that I explained the meaning of the "parallactic" term in that post, I assume you already know it. Unfortunately, the solution I explained was based on the use of a ScrollViewer to wrap a GridView. This was because the ScrollViewer exposes the ViewChanged event but the GridView don't. This is a minor issue in some cases, but lot of times the scrolling is not so smooth and fluid as the one of the GridView. Luckily XAML is so smart and beautiful that offers an alternative solution as the following video shows:

You have to be aware that all XAML controls are template based, as they are in Silverlight, and if you explore the template of the GridView you notice that is is based on an internal ScrollViewer. So, the idea is really simple in words; I can inherit a new control from the GridView, subtly change the template and attach to ScrollViewer events to update the parallactic background. Simle to say as it is simple to implement. First of all we have to change the template:

   1: <Setter Property="Template">
   2:     <Setter.Value>
   3:         <ControlTemplate TargetType="local:ParallacticGridView">
   4:             <Grid Background="{TemplateBinding Background}">
   5:                 <ItemsControl x:Name="ParallacticLayersElement" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
   6:                     <ItemsControl.ItemsPanel>
   7:                         <ItemsPanelTemplate>
   8:                             <Grid />
   9:                         </ItemsPanelTemplate>
  10:                     </ItemsControl.ItemsPanel>
  11:                 </ItemsControl>
  12:                 <Border BorderBrush="{TemplateBinding BorderBrush}" 
  13:                     BorderThickness="{TemplateBinding BorderThickness}" 
  14:                     Background="Transparent">
  15:                     <ScrollViewer x:Name="ScrollViewer" 
  16:                                   BringIntoViewOnFocusChange="{TemplateBinding ScrollViewer.BringIntoViewOnFocusChange}" 
  17:                                   HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}" 
  18:                                   HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}" 
  19:                                   IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}" 
  20:                                   IsHorizontalScrollChainingEnabled="{TemplateBinding ScrollViewer.IsHorizontalScrollChainingEnabled}" 
  21:                                   IsVerticalScrollChainingEnabled="{TemplateBinding ScrollViewer.IsVerticalScrollChainingEnabled}" 
  22:                                   IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}" 
  23:                                   IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}" 
  24:                                   TabNavigation="{TemplateBinding TabNavigation}" 
  25:                                   VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}" 
  26:                                   VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}" 
  27:                                   ZoomMode="{TemplateBinding ScrollViewer.ZoomMode}"
  28:                                   Background="Transparent">
  29:                         <ItemsPresenter HeaderTemplate="{TemplateBinding HeaderTemplate}" 
  30:                                         Header="{TemplateBinding Header}" 
  31:                                         HeaderTransitions="{TemplateBinding HeaderTransitions}" 
  32:                                         Padding="{TemplateBinding Padding}" />
  33:                     </ScrollViewer>
  34:                 </Border>
  35:             </Grid>
  36:         </ControlTemplate>
  37:     </Setter.Value>
  38: </Setter>




The yellow parts are the changes respect the original template. The add an outer grid that is used to contains the internal elements together with the added backgrounds. The ItemsControl instead let you to add a number of background elements that will be showed under the generated items, one on top of the other. The code is a fragment of a template that has to be put inside the generic.xaml. The next step is to implement the class of the control:

   1: public class ParallacticGridView : GridView
   2: {
   3:      private ItemsControl ParallacticLayersElement { get; set; }
   4:      private ScrollViewer ScrollViewer { get; set; }
   5:  
   6:      public static readonly DependencyProperty ParallacticLayersProperty =
   7:          DependencyProperty.Register("ParallacticLayers", typeof(List<FrameworkElement>), typeof(ParallacticGridView), new PropertyMetadata(new List<FrameworkElement>()));
   8:  
   9:      public List<FrameworkElement> ParallacticLayers
  10:      {
  11:          get { return (List<FrameworkElement>)GetValue(ParallacticLayersProperty); }
  12:          set { SetValue(ParallacticLayersProperty, value); }
  13:      } 
  14:  
  15:      public ParallacticGridView()
  16:      {
  17:          this.DefaultStyleKey = typeof(ParallacticGridView);
  18:      }
  19:  
  20:      protected override void OnApplyTemplate()
  21:      {
  22:          this.ParallacticLayersElement = this.GetTemplateChild("ParallacticLayersElement") as ItemsControl;
  23:  
  24:          foreach (FrameworkElement element in this.ParallacticLayers)
  25:              this.ParallacticLayersElement.Items.Add(element);
  26:  
  27:          this.ScrollViewer = this.GetTemplateChild("ScrollViewer") as ScrollViewer;
  28:          this.ScrollViewer.ViewChanged += ScrollViewer_ViewChanged;
  29:          base.OnApplyTemplate();
  30:      }
  31:  
  32:      private void ScrollViewer_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
  33:      {
  34:          foreach (FrameworkElement element in this.ParallacticLayersElement.Items.OfType<FrameworkElement>())
  35:          {
  36:              Thickness thickness = element.Margin;
  37:              var deltaX = (this.ScrollViewer.HorizontalOffset / this.ScrollViewer.ScrollableWidth) * (element.ActualWidth - this.ScrollViewer.ViewportWidth);
  38:              thickness.Left = -deltaX;
  39:              element.Margin = thickness;
  40:          }
  41:      }
  42:  }

The control has a ParallacticLayers property that is used to specify the items on the background. In the OnApplyTemplate I get a reference to the elements I need to manipulate. First of all the ScrollViewer which I attach the ViewChanges event. In the event handler I calculate the position of each layer with the same formula I've used in the previous article. To use the new control you can operate as follow:

   1: <controls:ParallacticGridView x:Name="gv" SelectionMode="None">
   2:     <controls:ParallacticGridView.ParallacticLayers>
   3:         <Image Stretch="UniformToFill" Source="Assets/Montreal_Twilight_Panorama_2006.jpg" Margin="0,0,0,0" />
   4:     </controls:ParallacticGridView.ParallacticLayers>
   5:     <controls:ParallacticGridView.ItemTemplate>
   6:         <DataTemplate>
   7:             <Border Width="150" Height="150" Background="#88FFFFFF" BorderThickness="1" BorderBrush="#88000000">
   8:                 <TextBlock FontSize="24" Text="{Binding}" 
   9:                            HorizontalAlignment="Center" 
  10:                            VerticalAlignment="Center" 
  11:                            Foreground="Black" />
  12:             </Border>
  13:         </DataTemplate>
  14:     </controls:ParallacticGridView.ItemTemplate>
  15:     <controls:ParallacticGridView.ItemsPanel>
  16:         <ItemsPanelTemplate>
  17:             <VariableSizedWrapGrid MaximumRowsOrColumns="4" VerticalAlignment="Top" Margin="100,100,100,0" />
  18:         </ItemsPanelTemplate>
  19:     </controls:ParallacticGridView.ItemsPanel>
  20: </controls:ParallacticGridView>

Interesting, in the ParallacticLayers property you can put more that one background. The result will be a set of backgrounds that scroll at a different speed.

Download: Elite.Parallactic.zip (7MB)

Windows 8 Apps: Change your project to run PlayReady successfully

2012-09-22T23:29:25+01:00 by Andrea Boschin

Today I wasted a lot of time to understand why, the code I wrote to implement PlayReady in a Windows 8 App didn’t work. I have ran the code lot of times, making changes to handle obscure hypothesis, just because my application was failing to load a DRM protected stream. When I finally found the error code issued by the MediaFailed event I went on the right way:

MF_MEDIA_ENGINE_ERR_SRC_NOT_SUPPORTED : HRESULT – 0x800700C1

I convinced myself that the problem wasn’t in the code but probably in the context I was compiling, this because the error 0x800700C1 means “is not a valid Win32 application”.

Comparing the project configuration with the one in the samples, I found the answer in a simple flag in the project configuration:

image

The “prefer 32-bit” flag is a new entry in the projects that target Microsoft .NET Framework 4.5. Its meaning is explained well in this post but in a few words in my case it was forcing the compiler to output to x86 (32-bit) instead of x64. Unfortunately PlayReady only supports 64bit runtime so, when the application ran it failed with the code I reported above.

So, when you’ll have to write applications that take advantage of the PlayReady SDK, please always remember to clear this flag because it is the sole way to have it working.

Windows 8 Metro series part #1

2012-09-12T00:25:31+01:00 by Andrea Boschin

Today, the last article of my series about Windows 8 "metro” applications I’m writing for http://www.silverlightshow.net has been published. The article is the first of the second part so it is the moment to collect together the work I’ve done up to july for the first part. If you like, the articles are available online on the SilverlightShow’s website at the addresser here reported:

 

Thanks to the great work the team made, the series is also available in a useful e-book, in the most common formats for your e-reader. You can buy it on the same website at this address http://www.silverlightshow.net/ebooks/win8_metro_1.aspx for only $2,99.

Metro: The SemanticZoom and the missing ItemTemplateSelector for ZoomedOutView

2012-09-07T23:41:11+01:00 by Andrea Boschin

Did you ever try to use the ItemTemplateSelector property for a grid view in SemanticZoom’s ZoomedOutView property? So the question is simpler than it appear: take a GridView, used to show items in a semantic zoom, - when the user zooms out - and try to give a different template to each item, using the usual template selector. And the answer is also simple: it does not work.

I suppose there is a good reason for this problem, but what it really matter to me is the solution. In a recent project I developed, the problem was really annoying and, after lot of try I found a work-around. The first thing to do is to setup the ZoomedOutView property:

   1: <SemanticZoom.ZoomedOutView>
   2:     <GridView ItemTemplate="{StaticResource ZoomedOutItemTemplate}" SelectionMode="None">
   3:         <GridView.ItemsPanel>
   4:             <ItemsPanelTemplate>
   5:                 <WrapGrid ItemWidth="300" ItemHeight="150" 
   6:                           VerticalAlignment="Center" HorizontalAlignment="Center" />
   7:             </ItemsPanelTemplate>
   8:         </GridView.ItemsPanel>
   9:     </GridView>
  10: </SemanticZoom.ZoomedOutView>

This is easy to understand given that there is nothing new. Please take only note I specified a simple ItemTemplate where the trick happens. The work-around is to use a ContentControl to map binding information and use the ContentTemplateSelector in place of the ItemTemplateSelector that is not working:

   1: <DataTemplate x:Key="ZoomedOutItemTemplate">
   2:     <ContentControl DataContext="{Binding Group}" Content="{Binding DataContext, RelativeSource={RelativeSource Mode=Self}}">
   3:         <ContentControl.ContentTemplateSelector>
   4:             <local:SemanticZoomTemplateSelector
   5:                 MajorTemplate="{StaticResource ZoomedOutItemMajorTemplate}"
   6:                 MinorTemplate="{StaticResource ZoomedOutItemMinorTemplate}"
   7:                 LightTemplate="{StaticResource ZoomedOutItemLightTemplate}"
   8:                 StrongTemplate="{StaticResource ZoomedOutItemStrongTemplate}"
   9:                 ModerateTemplate="{StaticResource ZoomedOutItemModerateTemplate}" />
  10:         </ContentControl.ContentTemplateSelector>
  11:     </ContentControl>
  12: </DataTemplate>

The tricky part of the solution is into the DataBinding of the ContentControl. If you simply try to bind the source property to the Content property, the template selector is not applied. I supposed the reason has to be found in the way the data binding happens so I had the idea of binding the property twice: first of all I bind the source to the DataContext property and then I use the RelativeSource to bind the Content property to the DataContext. And… it works!

Now I can implement the a Template selector to assign the right template based on the values of the source item:

   1: public class SemanticZoomTemplateSelector : DataTemplateSelector
   2: {
   3:     public DataTemplate MinorTemplate { get; set; }
   4:     public DataTemplate MajorTemplate { get; set; }
   5:     public DataTemplate ModerateTemplate { get; set; }
   6:     public DataTemplate StrongTemplate { get; set; }
   7:     public DataTemplate LightTemplate { get; set; }
   8:  
   9:     public SemanticZoomTemplateSelector()
  10:     {
  11:     }
  12:  
  13:     protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
  14:     {
  15:         EarthquakeGroup group = item as EarthquakeGroup;
  16:  
  17:         if (group != null)
  18:         {
  19:             if (group.Level == "major")
  20:                 return MajorTemplate;
  21:             if (group.Level == "minor")
  22:                 return MinorTemplate;
  23:             if (group.Level == "moderate")
  24:                 return ModerateTemplate;
  25:             if (group.Level == "strong")
  26:                 return StrongTemplate;
  27:         }
  28:  
  29:         return LightTemplate;
  30:     }
  31: }

The best thing of this solution is that the ContentControl does not changes how the item is shown. It does not require any change to the data templates and you can also use a resource dictionary.

If the solution is not clear here is a downloadable example: http://xamlplayground.org/assets/sources/XPG.MetroQuakes.zip (22kb)

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.

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.

Handling errors when calling network with Observable.FromEvent

2011-03-30T16:11:10+01:00 by Andrea Boschin

In my I've show a new way to write methods to call network resources like feeds, WCF methods and so on. I've proposed two solution that take advantage of Reactive Extension to call operations that follow the Begin-End pattern and also operation that use an event driven pattern. Today I would like to make another step forward to make the event driven side of the problem more reliable. Most of the times when you call the network you deal with this pattern instead of the Begin-End. Calling WCF and WebClient follow this pattern and we need to accurately handle the errors when we get the result from the calls.

The problem is that when you call a network resource this way you eventually get exceptions as a value of a property of the result instead of having them thrown as you may expect. This is obviously understandable due to the asynchronous nature of the calls. Also if the runtime will throw exceptions you would not be able to catch them because they are generated in another thread so the sole way to get them is that the runtime catch every exception and forward it using the Error property of the result. So here is how you commony handle the errors in network calls:

   1: public void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
   2: {
   3:     if (e.Error != null)
   4:     {
   5:         // there is an exception
   6:         MessageBox.Show(e.Error.Message);
   7:     }
   8:     else
   9:     {
  10:         // no error occured: do what you want with the result
  11:     }
  12: }

Using my Reactive Extensions way to the asynchronicity this issue may be a big problem because, since the Subscribe method is able to catch exceptions along the execution of the event, it does not understand about the Error resulting from an asynchronous network call. In my last example I showed this code:

   1: IObservable<SyndicationFeed> result = Observable.FromEvent<DownloadStringCompletedEventHandler, DownloadStringCompletedEventArgs>(
   2:     ev => new DownloadStringCompletedEventHandler(ev),
   3:     ev => client.DownloadStringCompleted += ev,
   4:     ev => client.DownloadStringCompleted -= ev)
   5:     .Select(o => o.EventArgs.Result)
   6:     .ConvertToFeed();

Unfortunately it works perfectly when the network call returns a valid response but it is unable to catch an exception if something goes wrong. To solve this problem I wrote an extension method that can collect possible exceptions and rethrow them. The trick is made using a base class named "AsyncCompletedEventArgs" that is used by every EventArgs returned by a network call. Having this common base class is key to write a single method to handle a lot of cases. Here is the code from the ThrowIfError() method:

   1: public static IObservable<IEvent<T>> ThrowIfError<T>(this IObservable<IEvent<T>> observable)
   2:     where T : AsyncCompletedEventArgs
   3: {
   4:     return observable.SelectMany(
   5:         o =>
   6:         {
   7:             if (o.EventArgs.Error != null)
   8:                 throw o.EventArgs.Error;
   9:  
  10:             return Observable.Return(o);
  11:         });
  12: }

The method is able to intercept and IObservable<IEvent<T>> that is the interface resulting from Observable.FromEvent() method. Once it receive the interface it examine the content and if it detects an error simple throw it. This make the runtime catch the exception and forward it to the OnError method of the Observer<T> that is the second parameter of a Subscribe method. If there is not any error the method simply returns the observable itself so the chain of method can be continued seamless. I use the SelectMany method to flatten the results from IObservable<IObservable<IEvent<T>>> (it's not a joke) to IObservable<IEvent<T>>. So now we can use the method everywhere we have to place a network call:

   1: public static IObservable<SyndicationFeed> DownloadFeedWebClient(Uri uri)
   2: {
   3:     WebClient client = new WebClient();
   4:  
   5:     IObservable<SyndicationFeed> result = Observable.FromEvent<DownloadStringCompletedEventHandler, DownloadStringCompletedEventArgs>(
   6:         ev => new DownloadStringCompletedEventHandler(ev),
   7:         ev => client.DownloadStringCompleted += ev,
   8:         ev => client.DownloadStringCompleted -= ev)
   9:         .ThrowIfError()
  10:         .Select(o => o.EventArgs.Result)
  11:         .ConvertToFeed();
  12:  
  13:     client.DownloadStringAsync(uri);
  14:  
  15:     return result;
  16: }

This does not change anything to the way you can call the DownloadFeedWebClient method because it returns always an IObservable<T> so you can simply Subscribe to it and specify and handler for the OnError part of the Observer<T>. To view an example please visit my .

A base class for threaded Application Services

2011-02-21T23:26:16+01:00 by Andrea Boschin

Continuing of my series about IApplicationServices I would like to propose a base class I've created to easily develop Application Services that runs a thread. There are lot of cases when you implement IApplicationService to run a parallel task that accomplish some kind of background tasks. I've collected all the redundant code inside a class I called ThreadedService. Extending this class you have a thread automatically started and stopped according with the application lifetime. Here is the class:

public abstract class ThreadedService : IDisposable, IApplicationService, IApplicationLifetimeAware
{
    /// <summary>
    /// Gets or sets the exit event.
    /// </summary>
    /// <value>The exit event.</value>
    private ManualResetEvent ExitEvent { get; set; }
 
    /// <summary>
    /// Gets or sets the wait handles.
    /// </summary>
    /// <value>The wait handles.</value>
    protected WaitHandle[] ExitHandles { get; set; }
 
    /// <summary>
    /// Initializes a new instance of the <see cref="ThreadedObject"/> class.
    /// </summary>
    public ThreadedService()
    {
        this.ExitEvent = new ManualResetEvent(false);
        this.ExitHandles = new WaitHandle[] { this.ExitEvent };
    }
 
    /// <summary>
    /// The main thread body
    /// </summary>
    protected abstract void ThreadProc();
 
    #region IDisposable Members
 
    /// <summary>
    /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
    /// </summary>
    public virtual void Dispose()
    {
        this.StopService();
    }
 
    #endregion
 
    #region IApplicationLifetimeAware
 
    public virtual void Starting()
    { }
 
    public virtual void Started()
    {
        ThreadStart listenThreadStart = new ThreadStart(ThreadProc);
        Thread thread = new Thread(listenThreadStart);
        thread.Start();
    }
 
    public virtual void Exiting()
    {
        this.ExitEvent.Set();
    }
 
    public virtual void Exited()
    { }
 
    #endregion
 
    #region IApplicationService
 
    public virtual void StartService(ApplicationServiceContext context)
    { }
 
    public virtual void StopService()
    { }
 
    #endregion
}

As already said the class is able to manage the background thread automatically but require a little level of collaboration when you develop the body of the thread. Infact after overriding the ThreadProc method you have to listen for the ExitEvent to be raised. When this event is set you have to exit from the service as soon as possible.

Saying we have to poll the newtork once every minute you can implement the ThreadProc the way I show it in the figure.

protected override void ThreadProc()
{
    this.Update();
 
    while (WaitHandle.WaitAny(this.ExitHandles, 5000) == WaitHandle.WaitTimeout)
        this.Update();
}

The procedure wait for the ExitEvent for a timeout. During this time the runtime is able to do something else but once the event is set the process is immediately exited. Something very simple but effective.

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