XAML Playground
about XAML and other Amenities

Windows Phone 8 Overview (Slides)

2013-06-07T11:55:00+01:00 by codeblock

Here is the slide set from my last talk on Windows Phone 8.

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

Model View ViewModel with Windows Store Application

2013-03-08T21:20:28+01:00 by codeblock

I reference here the slides from this night talk about the Model View ViewModel in a Windows Store app. The talk and the slides are in Italian but I figure out you can use google translate to get the translation in you language.

Model-View-ViewModel con Windows Store Apps

Thanks to all the people that listened to my presentation and asked me a question about this topic. If you need my help please feel free to contact me via blog contact form.

The “evil” in using “async void”

2013-02-19T01:57:03+01:00 by codeblock

Following a non-NDA session at the MVP Global Summit 2013, the speaker pointed me to an interesting argument that is the usage of “async” with methods returning void. This practice is used many times, more than you expect, and is a potential source of interesting bad issues that can cause unexpected crashes in your apps.

The problem with “async void” versus the opposite “async Task” is that a method declared this way is something like a “fire and forget”, where the fired part is the body of the method and the forget part may be the problem. Let say you have a situation like this:

   1: public void Run()
   2: {
   3:     try
   4:     {
   5:         DoSomething();
   6:     }
   7:     catch(Exception ex)
   8:     {
   9:         DisplayError(ex);
  10:     }
  11: }
  12:  
  13: public async void DoSomething()
  14: {
  15:     throw new Exception("Something gone wrong...");
  16: }

The “DoSomething” method here throws and exception, probably due to an error in its flow. The problem is that, when this method is called, the developer cannot use the “await” because the method is declared as “void”. So, when the exception is thrown, the “Run” method has already exited. The direct result is that the Exception is pushed to the UI Thread and in a Windows Store app this means that the app crashes, without any advice.

This situation is much more common they you expect. consider the Dispatcher.RunAsync method:

   1: Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
   2:     async () =>
   3:     {
   4:         // do something here...
   5:     });

The declaration of the RunAsync method requires a delegate declared as “void”, so when you ask for an async lambda, this is called as in the previous example. An exception in the body of the lambda expression causes exactly and application crash. The soluton is to wrap the RunAsync method is a mathod that returns a Task, so it can be awaited. So please, always avoid using “async void” in your code and you will not drive crazy trying to understand what is going wrong in your app.

SilverlightPlayground is moving to XAMLPlayground

2012-07-01T16:00:00+01:00 by codeblock

In the day I got my MVP for the 6th time in a row (the fifth under the Silverlight expertise), I would like to make it official, a change that someone can have miss. If you watch at the page header of this site, the title is now "XAML Playground", just to be witness of a biggest change that has happened in the previous months.

Many of you are aware that, after the technology shift predicted by Bob Muglia during October 2010, lot of things have changed in the horizon of the technology from which this site has born. Silverlight today is not only Silverlight but a set of technologies now have their roots starting from its seed. We have Silverlight on the Windows Phone, we have Silverlight on the Embedded systems and, mostly important we have Silverlight on Windows 8 under the name of XAML.

And it is exactly reflecting the name change that happened in Windows 8, that I decided to slightly change the title from "Silverlight" to "XAML".

The reason of this change is probably clear. I strongly believe that the power of Silverlight is now part of something much more bigger and it has a bright future. All these technologies have a sole common denominator that is XAML.

So, as it happened since the start of this year, expect in the future, a number of posts on Silverlight in the various flavour, for the Web, for Windows Phone, for Metro UI and probably also for Windows (ops... WPF). 

From now please be aware you can use three domains to reach this site:

http://www.silverlightplayground.org

http://www.xamlplayground.org

http://www.metroplayground.org

So definitely, it is all about XAML

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

Metro: Incrementally load GridView and ListView with ISupportIncrementalLoading

2012-06-10T21:58:36+01:00 by codeblock

Developers that usually deal with web applications know that one of the pillar of this kind of applications is the use of paged result sets because moving a huge number of records form the server to the browser is not a good idea. Metro applications suffer the same problem. No matter that metro applications are not strictly web applications, the application architecture imply that the connection to a datasource have to be wrapped by web service call so the need of limiting the usage of the network is a strong requirements.

Metro introduces a new interesting method to mange pagine of data. Since the use of a common paging is deprecated by guidelines the requirement is to automatically load records when a user is about to the end of the items available on the user interface. This may be an hard task to do with components like GridView and ListView but thanks to the ISupportIncrementalLoading interface it may be easy like a game.

The ISupportIncrementalLoading interface has to be implemented by a collection. When a GridView detects this interface in the class provided in the ItemsSource property, it automatically change its behavior and works loading items only when they really need to fill empty space because the user reached the end. The definition of the interface is pretty simple:

   1: public interface ISupportIncrementalLoading
   2: {
   3:     bool HasMoreItems { get; }
   4:     IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count);
   5: }

The HasMoreItems property simply inform the consumer when there is more items to load. But the core of the interface is the LoadMoreItemsAsync method. As the name suggests this method works asynchronously and it have to load a number of items. The count parameter represents the number of items the consumer needs but the body of the method can load a different number, based on its paging size, and have to return the this number as a result into the LoadMoreItemsResult class.

You may expect that the loaded items have to be returned by this method but it is not true. Remembering that the interface have to be implemented by a collection, the method have simply to append the loaded items to the collection itself. So, this interface needs that the collection raises a CollectionChange event to update the user interface. An exaample is for sure much more clear:

   1: public class NaturalNumbers : ObservableCollection<int>, ISupportIncrementalLoading
   2: {
   3:     public bool HasMoreItems
   4:     {
   5:         get { return true; }
   6:     }
   7:  
   8:     public IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count)
   9:     {
  10:         CoreDispatcher dispatcher = Window.Current.Dispatcher;
  11:  
  12:         return Task.Run<LoadMoreItemsResult>(
  13:             () =>
  14:             {
  15:                 int[] numbers = Enumerable.Range(this.LastOrDefault(), 100);
  16:                 
  17:                 dispatcher.RunAsync(
  18:                     CoreDispatcherPriority.Normal,
  19:                     () =>
  20:                     {
  21:                         foreach (int item in numbers)
  22:                             this.Add(item);
  23:                     });
  24:     
  25:                 return new LoadMoreItemsResult() { Count = 100 };
  26:     
  27:             }).AsAsyncOperation<LoadMoreItemsResult>();
  28:     } 
  29: }

If you attach an instance of this class to a GridView (or a ListView) it will show a series of natural numbers loading them incrementally when you scroll the control. Every time the GridView reach the edge of the screen it needs to load a number of items so, after having checked the HasMoreItems propertyit call the LoadMoreItemsAsync method and await for the end of the operation. Inside this method I start a new Task. This is required because I have to return something to wait to the caller and the AsAsyncOperation converts the Task to the requested async operation. Inside the thread I generate 100 numbers starting from last in the collection then I marshal this numbers to the ui thread and load them to the collection. Since the collection is Observable this updates the items in the user interface. Finally i return the number of items I generated.

As a more complex exercise I've prepared an example attached to the end of this post. This example use the incremental strategy to load images from Flickr search API. The application shown in the following screenshot implements the search contract. When a query is made it load a special collection and the items are loaded incrementally when the user scrolls the GridView.

screenshot_06102012_224133

For this purpose I've created a IncrementalSource class. This class implements the ISupportIncrementalLoading interface and is able to manage every data source that exposes a GetPage method. If you have this method already implemented in an application you can easily turn it to incremental loading in a breeze.

   1: public class IncrementalSource<T, K> : ObservableCollection<K>, ISupportIncrementalLoading
   2:     where T: IPagedSource<K>, new()
   3: {
   4:     private string Query { get; set; }
   5:     private int VirtualCount { get; set; }
   6:     private int CurrentPage { get; set; }
   7:     private IPagedSource<K> Source { get; set; }
   8:  
   9:     public IncrementalSource(string query)
  10:     {
  11:         this.Source = new T();
  12:         this.VirtualCount = int.MaxValue;
  13:         this.CurrentPage = 0;
  14:         this.Query = query;
  15:     }
  16:  
  17:     #region ISupportIncrementalLoading
  18:     
  19:     public bool HasMoreItems
  20:     {
  21:         get { return this.VirtualCount > this.CurrentPage * 25; }
  22:     }
  23:  
  24:     public IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count)
  25:     {
  26:         CoreDispatcher dispatcher = Window.Current.Dispatcher;
  27:  
  28:         return Task.Run<LoadMoreItemsResult>(
  29:             async () =>
  30:             {
  31:                 IPagedResponse<K> result = await this.Source.GetPage(this.Query, ++this.CurrentPage, 25);
  32:                 
  33:                 this.VirtualCount = result.VirtualCount;
  34:  
  35:                 await dispatcher.RunAsync(
  36:                     CoreDispatcherPriority.Normal,
  37:                     () =>
  38:                     {
  39:                         foreach (K item in result.Items)
  40:                             this.Add(item);
  41:                     });
  42:  
  43:                 return new LoadMoreItemsResult() { Count = (uint)result.Items.Count() };
  44:  
  45:             }).AsAsyncOperation<LoadMoreItemsResult>();
  46:     } 
  47:  
  48:     #endregion
  49: }

In my example I've implemented a Flickr class that use the flickr.photos.search API. So when a search comes I create an instance of this collection in the ItemsSource property of the GridView.

this.gv.ItemsSource = new IncrementalSource<Flickr, FlickrPhoto>(search);

If you want to try this beautiful application please download the full code from the link below. Provide your own Flicks Api Key and run the example in Visual Studio 2012 RC.

Download: http://www.silverlightplayground.org/assets/sources/XPG.Examples.IncrementalLoading.zip

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

Review: Mastering LOB Development for Silverlight 5: A Case Study in Action

2012-06-05T23:13:46+01:00 by codeblock

image

Braulio Diez, a friend of mine I known during the TechED 2008 in Barcelona, together with other authors has recently written a book about Silverlight 5. The "Mastering LOB Development for Silverlight 5: A Case Study in Action", published by PackLib is an interesting book that is able to point the light on the Silverlight topic, mixing together a good scan about Silverlight 5.0 features and a number of "cases study" that focus the attention of the reader on the power of this, still unmatched and irreplaceable, piece of technology.

In a time that seems to be pointed to the most new evolutions, inside the new version of Windows, mostly directly derived from Silverlight, reading this book may be a useful exercise to understand what it can do and what someone can still do using XAML instead of HTML5.

My thanks to Braulio for the pleasant reading.

http://www.packtpub.com/mastering-lob-development-silverlight-5/book

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

Metro: Implement a parallactic scrolling for your GridView

2012-05-19T00:56:36+01:00 by codeblock

A customer of mine asked me about how to create a "parallactic scrolling" for the background of a GridView. For people that do not know what it is, parallactic scrolling is when you have a background image scrolling slower than the foreground content. This tecnique is mostly used in games to give the impression of depth of field with the overlapping of a number of elements that moves slower when they apper to be far from the observer.

To have a good example of this beautiful effect you can try the music hub of your Windows Phone. The Panorama based scrolling, when coupled with a background image, automatically apply a parallactic effect when you move from a panel to the following.

Coming to Windows 8, there are some application installed by default that shows a similar effect. Weather and Finacial apps shows a partial parallactic effect when transitionig between the start screen and the right content. GridView, ScrollViewer and other controls does not automatically apply this effect (almost not in windows 8 CP), but a simple trick let you easily show the effect in your apps.

First of all you have to produce an element, that is greater than the viewport in the direction you desire your scrolling to work. In the application of my user group it is an image made of people an the total size is almost double of the medium size of a screen device. This image is aligned to left and goes out of the screen on the right. Here is the code:

   1: <Grid>
   2:     <Image x:Name="backImage" Margin="0,0,0,30" 
   3:             HorizontalAlignment="Left" VerticalAlignment="Bottom" 
   4:             Source="/Assets/parallax_people.png" Width="2250" Height="200" Opacity="0.5" />
   5:  
   6:     <ScrollViewer x:Name="hScroll" 
   7:                   Style="{StaticResource HorizontalScrollViewerStyle}" Margin="0">
   8:         <!-- insert your content here -->
   9:     </ScrollViewer>
  10: </Grid>

The trick I'm showing works only with ScrollViewer because it requires to handle the ViewChanged event, but you can for sure include a GridView into a ScrollViewer and have the effect enabled for the control. And obviously this also apply to ListView as well.

Now, going to codebehind is is required to subscribe the ViewChanged event. This event is raised every time the user scrolls the content. So I have to recalculate the offset of the background using the HorizontalOffset property and to map the value to the total width of the image. Here is the code:

   1: private void hScroll_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
   2: {
   3:     var delta = (this.hScroll.HorizontalOffset / this.hScroll.ScrollableWidth) * (backImage.ActualWidth - this.hScroll.ViewportWidth);
   4:     this.backImage.Margin = new Thickness(-delta, 0, 0, 30);
   5: }

Once you have connected the method to the View the trick is done. In this code I use the Margin property to move the image. At the first sight you would have used a TranslationTranform. Unfortunately the Render tranforms clips the image so I finally adopted the Margin property with a negative value.

In my example you can tune the speed of the content  varying the width of the background image, but nothing else is required.

Metro: A simple class to handle retry on network calls

2012-05-18T00:31:23+01:00 by codeblock

After you start working with metro-style applications, you may be concerned by the extensively adopted asyncronous model. If you ever used Silverlight you can be aware that this model comes directly as an inheritance from it. In metro-style applications this model is taken to the extreme consequences. As an example WinRT exposes all the operations that takes longer than 50ms with an asyncronous pattern. But the most frequent case where you meet asynchronicity, is when you call the network.

The use of Task Parallel Library offers anumber of interesting opportunities to handle asynchronous operations and the benefits can make your code most simple and reusable. Recently I've created an interesting class (I called it NetworkCallManager). This class wraps every network call and let you control the flow of a call in the case it returns an error. It is common to handle timeouts, authentication issues and poor network connectivity and if you read the guidelines you know that they suggests you to let the user retry the failed operation. Here is the code I wrote:

   1: public class NetworkCallManager
   2: {
   3:     public event EventHandler<NetworkErrorEventArgs> NetworkError;
   4:  
   5:     protected virtual void OnNetworkError(NetworkErrorEventArgs args)
   6:     {
   7:         EventHandler<NetworkErrorEventArgs> handler = this.NetworkError;
   8:  
   9:         if (handler != null)
  10:             handler(this, args);
  11:     }
  12:  
  13:     public async Task<T> Execute<T>(Func<Task<T>> task)
  14:     {
  15:         bool retry = false;
  16:  
  17:         do
  18:         {
  19:             Exception error = null;
  20:  
  21:             try
  22:             {
  23:                 return await task();
  24:             }
  25:             catch (Exception ex)
  26:             {
  27:                 error = ex;
  28:             }
  29:  
  30:             if (error != null)
  31:             {
  32:                 NetworkErrorEventArgs args = new NetworkErrorEventArgs(error);
  33:                 this.OnNetworkError(args);
  34:                 retry = !args.Cancel;
  35:             }
  36:  
  37:         } while (retry);
  38:  
  39:         throw new NetworkOperationCancelledException("Network operation has been cancelled");
  40:     }
  41: }

The main method, responsible to place the network call, is named Execute. It receives a Task<T> where T is compatible with the return type of the network call we have to execute. The important thing to understand is that you have tu use a lambda expression because the code inside the method can recall this function lot of times. The method works as a pass-through function since it returns the same type as the function passed. So when the task is completed you can get directly the result.

Inside the body the method starts a loop where it runs the task and handles exceptions. When an exception is raised it gracefully handle the error and notifies it to the caller. The user can choose to break the operation or to retry. Here is how you can use the class:

   1: // omissis
   2:  
   3: NetworkCallManager ncm = new NetworkCallManager();
   4: ncm.NetworkError += HandleNetworkError;
   5:  
   6: try
   7: {
   8:     this.Speeches = await ncm.Execute<IEnumerable<SpeechDTO>>(() => this.DataService.GetSpeechesInYears(5));
   9: }
  10: catch (NetworkOperationCancelledException ex)
  11: {
  12:     // swallow
  13: }
  14: catch (Exception ex)
  15: {
  16:     this.DialogService.ShowGenericError(ex.Message);
  17: }
  18: finally
  19: {
  20:     ncm.NetworkError -= HandleNetworkError;
  21: }
  22:  
  23: private async void HandleNetworkError(object sender, NetworkErrorEventArgs e)
  24: {
  25:     e.Cancel = await this.DialogService.ShowNetworkError(e.Error);
  26: }
  27:  
  28: // omissis

This pattern let you to use the wrapper in a trasparent way and directy get the result. It also raises a specific exception when the user choose to stop the operation instead of retry. To me this spered me to implemend this flow directly into the page.

Implement a NavigationService for MVVM in Metro Applications

2012-05-10T00:37:56+01:00 by codeblock

When you write a Metro-style app using the MVVM pattern, you are requested to abstract navigation for the pattern purposes. The problem comes from having navigation methods (Navigate, GoBack, etc...) available only in the View via the Frame control and navigate from the ViewModel may be an hard task.

During the development of my last metro app for my user group, I found a stylish way of creating a NavigationService to be injected in ViewModels. The trick is to create a NavigationService class and let it create and initialize the RootFrame and inject it into the Window.Current.Content.

   1: public class NavigationService : INavigationService
   2: {
   3:     protected Frame RootFrame { get; private set; }
   4:  
   5:     public NavigationService()
   6:     {
   7:         this.RootFrame = new Frame();
   8:     }
   9:  
  10:     public void Initialize(Window window, bool activate = true)
  11:     {
  12:         if (window.Content == null)
  13:             window.Content = this.RootFrame;
  14:  
  15:         if (activate)
  16:             window.Activate();
  17:     }
  18:  
  19:     public virtual void Navigate(Type destination, object parameter = null)
  20:     {
  21:         // avoid navigation if current equals to destination
  22:  
  23:         if (this.RootFrame.CurrentSourcePageType != destination)
  24:             this.RootFrame.Navigate(pageType, parameter);
  25:     }
  26:  
  27:     public virtual void GoBack()
  28:     {
  29:         if (this.RootFrame.CanGoBack)
  30:             this.RootFrame.GoBack();
  31:     }
  32:     
  33:     public virtual void GoForward()
  34:     {
  35:         if (this.RootFrame.CanGoForward)
  36:             this.RootFrame.GoForward();
  37:     }
  38:     
  39:     public virtual bool CanGoBack
  40:     {
  41:         get { return this.RootFrame.CanGoBack; }
  42:     }
  43:     
  44:     public virtual bool CanGoForward
  45:     {
  46:         get { return this.RootFrame.CanGoForward; }
  47:     }
  48:     
  49:     public virtual void Save()
  50:     {
  51:         throw new NotImplementedException();
  52:     }
  53:     
  54:     public virtual void Load()
  55:     {
  56:         throw new NotImplementedException();
  57:     } 
  58: }

The previous box shows the code of my service: first of all the service implements an interface. This serves for the dependency injection since ViewModel only accept INavigationService to make it testable. The Initialize method sets the Window.Content to the frame instance I created in the constructor. Finally the class implements all the required navigation methods. Interesting to say, you can implement Save and Load using Framee.GetNavigationStatus and Frame.SetNavigationStatus to persist the navigation backstack when your app is terminated. Here is how to use the class in the App.xaml.cs:

   1: protected override void OnLaunched(LaunchActivatedEventArgs args)
   2: {
   3:     // get the instance from Injection Container
   4:     INavigationService ns = this.Container.Resolve<INavigationService>();
   5:  
   6:     if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
   7:     {
   8:         // load state if app was terminated
   9:         ns.Load();
  10:     }
  11:     
  12:     // initialize current window
  13:     ns.Initialize(Window.Current);
  14:  
  15:     // navigate to the first page
  16:     ns.Navigate(Pages.MainPageType);
  17: }
  18:  
  19: private void OnSuspending(object sender, SuspendingEventArgs e)
  20: {
  21:     // get the instance from Injection Container
  22:     INavigationService ns = this.Container.Resolve<INavigationService>();
  23:  
  24:     // save navigation status
  25:     ns.Save();
  26: }

This code shows also how to load and save to persistence media the navigation history. In this way when you return to the app after it has been terminated, it can reload again an exact navigation.

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);
   4:  
   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
   2:  
   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;
   7:  
   8:      object commandParameter;
   9:  
  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;
  17:  
  18:      if (command != null)
  19:          command.Execute(commandParameter);
  20: }
  21:  
  22: /// ... omissis
  23:  
  24: private sealed class BindingEvaluator : FrameworkElement
  25: {
  26:     /// <summary>
  27:     /// Instance of the binding to evaluate
  28:     /// </summary>
  29:     private Binding Binding { get; set; }
  30:  
  31:     #region Value
  32:  
  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));
  38:  
  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:     }
  50:  
  51:     #endregion
  52:  
  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: } 
  65:  

Conclusion

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:

http://xamlplayground.org/page/Silverlight-WP7-RFB.aspx

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
http://www.windowsphone.com/it-IT/apps/ef2ef5b9-192c-4d77-a684-c1e69bea24fa

Standard Edition: full control
http://www.windowsphone.com/it-IT/apps/e6c631e6-f6c4-49e5-98a9-d49eea8212cf

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;
   6:  
   7:       // initialize unmanager pointers
   8:       IntPtr hDC = IntPtr.Zero,
   9:              hMemDC = IntPtr.Zero,
  10:              desktop = IntPtr.Zero;
  11:  
  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);
  20:  
  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:           };
  27:  
  28:           // create a bitmap compatible with desktop
  29:           IntPtr hBitmap = Gdi32.CreateCompatibleBitmap(hDC, size.Width, size.Height);
  30:  
  31:           if (hBitmap != IntPtr.Zero)
  32:           {
  33:               // select memory Device Context into the new bitmap
  34:               IntPtr hOld = (IntPtr)Gdi32.SelectObject(hMemDC, hBitmap);
  35:  
  36:               // copy the desktop to the memory handle
  37:               Gdi32.BitBlt(hMemDC, 0, 0, size.Width, size.Height, hDC, 0, 0, (int)TernaryRasterOperations.SRCCOPY);
  38:  
  39:               // select the memory Device Context into the bitmap
  40:               Gdi32.SelectObject(hMemDC, hOld);
  41:  
  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:               };
  57:  
  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];
  61:  
  62:               // initialize a WriteableBitmap to output the result
  63:               bmap = new WriteableBitmap(size.Width, size.Height);
  64:  
  65:               // copy bitmap to byte array
  66:               Gdi32.GetDIBits(hMemDC, hBitmap, 0, (uint)size.Height, data, ref bi, 0);
  67:  
  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:       }
  86:  
  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();
   4:  
   5:     Delay(1000,
   6:           () =>
   7:           {
   8:               try
   9:               {
  10:                   BitmapSource source = ScreenCapture.GetDesktopImage();
  11:  
  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: }
  28:  
  29: private void Delay(int timeout, Action action)
  30: {
  31:     Task task = new Task(
  32:         () =>
  33:         {
  34:             Thread.Sleep(timeout);
  35:  
  36:             Deployment.Current.Dispatcher.BeginInvoke(action);
  37:         });
  38:  
  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