XAML Playground
about XAML and other Amenities

How to configure an AuthenticationDomainService using Ria Services Class Library

2009-11-06T11:36:01+01:00 by Andrea Boschin

Using a Ria Services Class library to collect DomainServices and DomainContexts in a solution is a good practice because everyone know the value of having classes separated in projects instead of having them in the web project.

If you try to create this kind of project and then you add an Authentication Domain Service with the July 2009 CTP of Ria Services you will find two major drawbacks. First of all you will notice the generated code does not contains a RiaContext class. RiaContext is the class responsible to handle the User and roles and configure the type of Authentication to use in the application.

To workaround to this problem you may simply write by hand this class and put it in the client side part of the Ria Services library project. The code can be copied by an AuthenticationDomainContext generated in the web project but it is very simple and I show you the code here:

   1: public sealed partial class RiaContext : System.Windows.Ria.RiaContextBase
   2: {
   3:     #region Extensibility Method Definitions
   4:  
   5:     partial void OnCreated();
   6:  
   7:     #endregion
   8:  
   9:     public RiaContext()
  10:     {
  11:         this.OnCreated();
  12:     }
  13:  
  14:     public new static RiaContext Current
  15:     {
  16:         get
  17:         {
  18:             return ((RiaContext)(System.Windows.Ria.RiaContextBase.Current));
  19:         }
  20:     }
  21:  
  22:     public new User User
  23:     {
  24:         get
  25:         {
  26:             return ((User)(base.User));
  27:         }
  28:     }
  29: }

With this class you can configure the Authentication Domain Context as you did with the generated class. So you have to add it to the App.config, in the ApplicationLifetimeObjects tag and then add a kind of authentication like the WindowsAuthentication and FormsAuthentication.

The second drawback is that if you run the project this way and then you call the Login() method (or any other method) of the RiaContext you will get an error:

The DomainContextType is null or invalid and there are no contexts generated from AuthenticationBase<T>

This probably come from the fact that the RiaContext is not correctly initializated so when the class search for a valid domaincontext to handle the Login call it fails because it does not find it. The tip to correct this behavior is to specify the DomainContext property in the Authentication you have choosed. Here is how to change the App.xaml file:

   1: <Application.ApplicationLifetimeObjects>
   2:     <slpgria:RiaContext>
   3:         <slpgria:RiaContext.Authentication>
   4:             <appsvc:FormsAuthentication>
   5:                 <appsvc:FormsAuthentication.DomainContext>
   6:                     <slpgdc:MyAuthenticationDomainContext />
   7:                 </appsvc:FormsAuthentication.DomainContext>
   8:             </appsvc:FormsAuthentication>
   9:         </slpgria:RiaContext.Authentication>
  10:     </slpgria:RiaContext>
  11: </Application.ApplicationLifetimeObjects>

As you can see you have simply to give an instance of the generated Authentication Domain context class to the FormsAuthentication (or Windows Authentication as well). The RiaContext need to have this instance to make the calls to the BL methods in the Domain Service.

I really do not know if this behavior will be corrected in the next releases of RiaServices. The solution is pretty simple but take me some hours to understand what are going wrong. So I hope this may help you to spare some time making your experiments with the current release.

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

Handling duplicated connections on Polling Duplex

2009-10-23T00:46:00+01:00 by Andrea Boschin

The last tip I would like to propose is a tecnique to avoid a single client machine connect multiple times to the same polling server. This may be the case when the user starts two or more instances of the browser or open the same page in multiple tabs. In this scenario may be unuseful to have every page connected to the server.

In Silverlight 3.0 there is a way to check when a plugin has been loaded many times. When you try to create a LocalReceiver with the same name from two instances you get an exception because they cannot share the same name. So using a LocalReceiver you can check if another browser is open.

   1: public override void Start()
   2: {
   3:     LocalMessageReceiver receiver = this.CreateReceiver();
   4:  
   5:     if (receiver != null)
   6:     {}  // receiver created: I'm the master...
   7:     else
   8:     {}  // cannot create receiver: I'm a slave...
   9: }
  10:  
  11: private LocalMessageReceiver CreateReceiver()
  12: {
  13:     try
  14:     {
  15:         LocalMessageReceiver receiver = new LocalMessageReceiver("PollingReceiver");
  16:         receiver.Listen();
  17:         return receiver;
  18:     }
  19:     catch(ListenFailedException)
  20:     {
  21:         return null;
  22:     }
  23: }

 

Checking the presence of another instance is only half of the work to do. When you detect you are a slave in the machine you need to avoid connecting - slave does nothing because a master already exists - and probably you have to change the user interface to let the user know that there is another instance running.

In my application I need to check the presence of the master every few seconds to let a slave becoming a master. To do this I've created two classes MasterPollingClientCode  SlavePollingClientCore implementing the same interface IPollingClientCore. The first class connect to the server and the other class simply does nothing.

   1: public override void Start()
   2: {
   3:     LocalMessageReceiver receiver = this.CreateReceiver();
   4:  
   5:     if (receiver != null)
   6:         this.Core = new MasterPollingClientCore(this.SessionId, this.EndPoint, receiver);
   7:     else
   8:         this.Core = new SlavePollingClientCore(this.LocalId, 
                          new LocalMessageSender("PollingSender" + this.LocalId.ToString()));
   9:  
  10:     this.Core.AlarmReceived += new EventHandler<NotifyAlarmReceivedEventArgs>(Core_AlarmReceived);
  11:     this.Core.Connected += new EventHandler(Core_Connected);
  12:     this.Core.Disconnected += new EventHandler(Core_Disconnected);
  13:     this.Core.Fault += new EventHandler<PollingFaultEventArgs>(Core_Fault);
  14:     this.Core.Start();
  15:     base.Start();
  16: }
 

The container class, then starts a thread. This thread try to create a new LocalReceiver and when it is able to get an instance it change the core class from slave to master and connect to the server. This way the client is always connected to the server with alwasy one simple connection:

   1: protected override void ThreadProc()
   2:     {
   3:         Debug.WriteLine("ThreadProc");
   4:  
   5:         while(WaitHandle.WaitTimeout == WaitHandle.WaitAny(this.ExitHandles, 5000))
   6:         {
   7:             if (this.Mode != PollingClientMode.Master)
   8:             {
   9:                 Deployment.Current.Dispatcher.BeginInvoke(
  10:                     ()=> this.TryConvertToMaster());
  11:             }
  12:         }
  13:     }
  14:  
  15:     /// <summary>
  16:     /// Tries the convert to master.
  17:     /// </summary>
  18:     private void TryConvertToMaster()
  19:     {
  20:         Debug.WriteLine("TryConvertToMaster");
  21:  
  22:         LocalMessageReceiver receiver = this.CreateReceiver();
  23:  
  24:         if (receiver != null)
  25:         {
  26:             Debug.WriteLine("created");
  27:  
  28:             // detach all
  29:             this.Core.Stop();
  30:             this.Core.AlarmReceived -= new EventHandler<NotifyAlarmReceivedEventArgs>(Core_AlarmReceived);
  31:             this.Core.Connected -= new EventHandler(Core_Connected);
  32:             this.Core.Disconnected -= new EventHandler(Core_Disconnected);
  33:             this.Core.Fault -= new EventHandler<PollingFaultEventArgs>(Core_Fault);
  34:             // create new core
  35:             this.Core = new MasterPollingClientCore(this.SessionId, this.EndPoint, receiver);
  36:             // attach all
  37:             this.Core.AlarmReceived += new EventHandler<NotifyAlarmReceivedEventArgs>(Core_AlarmReceived);
  38:             this.Core.Connected += new EventHandler(Core_Connected);
  39:             this.Core.Disconnected += new EventHandler(Core_Disconnected);
  40:             this.Core.Fault += new EventHandler<PollingFaultEventArgs>(Core_Fault);
  41:             this.Core.Start();
  42:         }
  43:     }
 
 

If you are brave you can try to implement a communication between Slave and Master using a LocalSender. Using the code I provider this task cannot be too hard.

Good Work

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

How to avoid flooding a PollingDuplex server

2009-10-06T14:37:39+01:00 by Andrea Boschin

Returning on the PollingDuplex argument, today I would like to illustrate a tecnique I used to avoid the flooding in my Polling Duplex service. The problem come from the fact that my server retain a list of connected clients and is unable to detect the disconnection in a short time. After a while the notification from the server to the disconnected client will timeout so the server handle the timeout and remove the client from its list. But if for some reason a client Register itself multiple times the server notification list will grow and this may become a problem causing the service to slow down its response time.

In a recent project I have to address this issue because of the way the polling client works. Imagine having a instant messaging client using PollingDuplex in all the pages of a portal. When the user navigate in the website the polling client will repeatly connect and disconnect from the polling server because the user may change page after short time.

How to generate a persistent ClientID

To handle this problem I need to have a globally unique id identifing the connecting client. If the ID is unique across different connected clients the server can use this ID to search previuos instances of the client in his notification list and if found it discart the old client and replace it with the new one. The solution is pretty simple but it require the ability to generate a very unique id (obviously a Guid) and then persist it across different browser session.

The trick is to use the Isolated Storage. The first time I start the client it generate the Guid and save it in the IsolatedStorageSettings collection. Then it use the guid to connect and register to the polling server.

All the other times the client find the Guid in the IsolatedStorageSettings and avoid to generate another Guid but use the old identifier. Here is the code to generate the guid or take id from the storage:

   1: private void Application_Startup(object sender, StartupEventArgs e)
   2: {
   3:     Guid key;
   4:  
   5:     if (!IsolatedStorageSettings.ApplicationSettings.Contains("InstanceKey"))
   6:     {
   7:         key = Guid.NewGuid();
   8:         IsolatedStorageSettings.ApplicationSettings["InstanceKey"] = key;
   9:         IsolatedStorageSettings.ApplicationSettings.Save();
  10:     }
  11:     else
  12:         key = (Guid)IsolatedStorageSettings.ApplicationSettings["InstanceKey"];
  13:  
  14:     this.RootVisual = new MainPage(key.ToString());
  15: }

I put the code in the Application_Startup method then I pass the key to the MainPage constructor because it must use the guid to connect to the server.

On the server side I've slightly changed the Register method and the Polling thread to handle the new guid. First of all I request the id in the Register method:

   1: public void Register(string sessionId)
   2: {
   3:     IPollingServiceClient client =
   4:         OperationContext.Current.GetCallbackChannel<IPollingServiceClient>();
   5:  
   6:     PollingMonitor.Current.Register(client, sessionId);
   7: }

Then the server checks his notification list to add or change the callback client:

   1: /// <summary>
   2: /// Adds the specified item.
   3: /// </summary>
   4: /// <param name="item">The item.</param>
   5: public void Add(IPollingServiceClient client, string sessionId)
   6: {
   7:     var found = (from c in this
   8:                  where c.SessionId == sessionId
   9:                  select c).SingleOrDefault();
  10:  
  11:     if (found != null)
  12:         found.ChangeClient(client);
  13:     else
  14:         this.Add(new PollingClient(client, sessionId));
  15: }

The ChangeClient() method simply put the new callback client in the object instance representing the client in the list.

There are only two drawbacks in this tecnique. The first is that the user can clear his IsolatedStorage using the Silverlight context menu. This deletes the saved Guid so the next time the client connect to the server it generate another Guid. On the other side someone may discover some privacy concerns on having an id globally identifying the client because this may become a way to track the user activities. You have to be aware of this problem and eventually you can mitigate the problem using a TTL to invalidate the Guid after some hours or days so the client will change the Guid and the tracking become hardest.

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

Handling faults on PollingDuplex while server is not available

2009-09-25T15:57:34+01:00 by Andrea Boschin

During the development of the project I'm currently working I've implemented a polling duplex client and I found some improvements to the code I've published some weeks ago in this post.

The problem I would like to answer here is caused by server unavailability that may origin in many causes. In my scenario I'm using a WCF service hosted by Internet Information Server. While I'm using a server-side thread running in the context of the Application Pool there may be some conditions where Application Pool is recycled so the server thread is aborted and the PollingDuplex communication stops.

There is many reasons why we have to avoid this condition. In my case it is important that the client continue receive updates from the polling server without it require a page refresh from the user. So I've implemented a fault handling procedure that let my client detect when the server become unavailable and then it retry connecting and restart server side thread.

First of all we have to write a registration procedure. My duplex channel work using a Register() ServiceOperation called by the client that subscribe the client in the server thread for updates notification. The client callback contract has a single NotifyAlarm() method used by the server to notify messages to client. Here is the client-side code I use to start the polling:

   1: /// <summary>
   2: /// Registers this instance.
   3: /// </summary>
   4: private void Register()
   5: {
   6:     this.Client = new PollingServiceClient(
   7:         new CustomBinding(
   8:             new PollingDuplexBindingElement
   9:                 {
  10:                     InactivityTimeout = new TimeSpan(1, 0, 0),
  11:                     ClientPollTimeout = new TimeSpan(0, 1, 0)
  12:                 },
  13:             new BinaryMessageEncodingBindingElement(),
  14:             new HttpTransportBindingElement()),
  15:         this.EndPoint);
  16:  
  17:     this.Client.NotifyAlarmReceived += 
  18:         new EventHandler<NotifyAlarmReceivedEventArgs>(Client_NotifyAlarmReceived);
  19:     this.Client.InnerChannel.Faulted += 
  20:         new EventHandler(Client_Faulted);
  21:     this.Client.RegisterCompleted += 
  22:         new EventHandler<System.ComponentModel.AsyncCompletedEventArgs>(Client_RegisterCompleted);
  23:     this.Client.RegisterAsync(this.SessionId);
  24: }

To handle channel fault I subscribe the Faulted event in the InnerChannel. I cannot find any other way to detect when the polling fail due to server unavailability. If you trace the polling of the client and then simulate the server unavailability, recycling the application pool you will see a 404 error (if you use ClientHttpStack the error will be more specific).

Untitled

When this error occur the InnerChannel.Faulted event is raised so you can restart the polling calling the Register() method again. In the Faulted event handler I simply call the Register method again. 

   1: /// <summary>
   2: /// Handles the Faulted event of the Client control.
   3: /// </summary>
   4: /// <param name="sender">The source of the event.</param>
   5: /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
   6: void Client_Faulted(object sender, EventArgs e)
   7: {
   8:     Deployment.Current.Dispatcher.BeginInvoke(
   9:         () =>
  10:         {
  11:             this.OnDisconnected();
  12:             this.Register();
  13:         });
  14: }

The better will be starting a Timer to retry connection on a regular timeout to let the client returning online after longer server unavailability. This may be useful also when we start the polling because we can dowload the Silverlight application from a server but then it starts the polling to another server. So I've added some code in the RegisterCompleted event handler and when I get an exception from the Register() method I start a separate thread. It waits for 60 seconds then recall the Register() method again.

   1: void Client_RegisterCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
   2: {
   3:     if (e.Error == null)
   4:         this.OnConnected();
   5:     else
   6:     {
   7:         this.OnFault(e.Error);
   8:  
   9:         ThreadPool.QueueUserWorkItem(
  10:             (o) =>
  11:             {
  12:                 Thread.Sleep(60000);
  13:  
  14:                 Deployment.Current.Dispatcher.BeginInvoke(
  15:                     () => this.Register());
  16:             });
  17:     }
  18: }

You have to be aware that the Faulted event require you to marshal the context of the thread before updating any UI element. In my code I raise an event of a wrapper object to let UI reflect the temporary disconnection. So I have to use the Dispatcher to marshal the Thread to the UI.

This is all for now. I will write more on this argumet on the next days to handle a different condition.

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

A Prism (Unity) Service to create Views

2009-08-31T21:10:03+01:00 by Andrea Boschin

After a long summer pause I’m back with this new post. This time I want to investigate an aspect of the Model-View-ViewModel pattern programming with Silverlight. During the summer I've started working on an application where I used Prism to implement MVVM and I found useful to write some code to easily create instance of views during application inizialization and during its lifetime. I really do not know if this is the better solution but I found it easy and useful so I've decided to share it with you. Let me say in this post I assume you are already aware of the reasons and benefits coming from the usage of the popular Model-View-ViewModel pattern and how the pattern works. I also assume you have a minimal knowledge of the Prism toolkit and Unity.

The relationship between the View and the ViewModel

In this section I would like to depict how the View and ViewModel collaborate and what we have to do to create an instance of a View and of its own ViewModel at the sole purpose of preparing the field for explaining my solution.

In the MVVM pattern the View represent the user interface and the ViewModel represent the business logic required to drive the informations displayed on the View. This way, every time we have to create a View we also have to create a specific ViewModel exposing the expected informations to be displayed. The ViewModel is not aware of the View, so It does not know how its properties are consumed, but it simply publish some data through some properties and the View will attach these properties using DataBinding.

What I've said reveal almost two things. The first is that the View does not know how the ViewModel works internally, but it have to know the structure of its surface. In other words the ViewModel have to implement a given well-known "interface" to let the View working fine. This interface contains only properties the View is expected to attach. This implementation is not truly required by the pattern but we can think it is near to reality.

The other thing we have to know is that to let the view binding to the ViewModel, we have to put the ViewModel in the DataContext of the View. So, the creation of the View involve the creation of a specific ViewModel -possibly implementing a given interface - and the assignment of this instance to the DataContext property of the View. Translating this concept in code we have to write something like this:

   1: MyView view = new MyView() 
   2: { 
   3:     DataContext = new MyViewModel() 
   4: }; 


In my projects I do not like to write this code because it does not let me impose to the ViewModel an interface implementation. I can obviously implement the interface but there is nothing checking that this implementation has been done. To avoid this problem I've decided to create a service I use every time I need to create a View. The service is responsible to check that the ViewModel implements a specific interface. So the creation of a View become this:

   1: // assuming "vbs" is an instance of the service 
   2: MyView view = vbs.CreateView<MyView>(); 

What is a service?

Before entering the service implementation details, I would like to explain what is a Service. As I've already said in the previous paragraphs I'm using , a.k.a . Prism is a collection of useful tools to let the developer apply easily the most common architectural patterns. For the purpose of this article we will use , a dependency injection container recently ported to Silverlight from the Microsoft Pattern and Practice team. It is available inside the Prism collection.

Unity is an "" container. It let you create and register instances of classes - giving them a lifetime manager responsible of how and when the class is created and destroyed - and then locate these classes when you need to use them. Creating a class and registering it in the IOC container let you having something similar to a service, always available and discoverable, you may dedicate to specific responsibility.

The purpose of Unity is to promote layer decoupling to enable unit testing of the applications, but this is out of the scope of this article. If you would like to read something about this argument please refer to the Unity home page on codeplex: http://www.codeplex.com/unity.

Anatomy of the ViewBuilderService

Now that I have briefly explained how a service works it is time to explain the basis of my ViewBuilderService. The trick is that the View have to declare somewhere the interface it expects the ViewModel to implement. We may have an interface "IMyViewModel" and a view "MyView" that can consume a ViewModel implementing this interface. Using a simple custom attribute we can decorate the View codebehind with the interface:

   1: [ViewModel(typeof(IMyViewModel))]
   2: public partial class MyView : UserControl
   3: {
   4:     public MyView()
   5:     {
   6:     }
   7: }

Declaring a custom Attribute is simple and it enable the ViewBuilderService to discover the interface to search for in the IOC container. In the next box there is the declaration of the ViewModelAttribute where I use the AttributeUsage attribute to inform the compiler where it have to expect the attribute to be applied.

   1: [AttributeUsage(AttributeTargets.Class)]
   2: public class ViewModelAttribute : Attribute
   3: {
   4:     public Type ViewModelType { get; set; }
   5:  
   6:     public ViewModelAttribute(Type viewModelType)
   7:     {
   8:         this.ViewModelType = viewModelType;
   9:     }
  10: }

To connect a ViewModel to its own interface we need to create the ViewModel and register it into the IOC container. This way the ViewBuilderService can read the ViewModelAttribute on the View and ask the container to resolve the interface and give us the ViewModel instance to put in the DataContext. The best place to register the ViewModels is a Module we have declared in the Unity Bootstrapper. In the sample attached to this article I've omitted to use a Module for the purpose of not complicate the sample. So the ViewModels are registered in the Bootstrapper itself.

   1: /// <summary>
   2: /// Registers the types.
   3: /// </summary>
   4: private void RegisterTypes()
   5: {
   6:     this.Container.RegisterType<IMyViewModel, MyViewModel>();
   7: }

Now all is ready and we can create the service. We have to remember that the service has to be registered in the IOC contained to be discoverable using the ServiceLocator. So we start creating a class that implements an interface IViewBuilderService:

   1: public class ViewBuilderService : IViewBuilderService
   2: {
   3:     private static IUnityContainer TheContainer { get; set; }
   4:  
   5:     public ViewBuilderService (IUnityContainer theContainer)
   6:     {
   7:         this.TheContainer = theContainer;
   8:     }
   9: }

The IViewBuilderService interface have to expose only a CreateView<T>() method we will implement in the service. This method is responsible of finding the ViewModel in the container, creating the View we specified in the T parameter and finally connect view and viewmodel together.

   1: public T CreateView<T>()
   2:     where T : UserControl, new()
   3: {
   4:     ViewModel vm = this.GetViewModel(typeof(T));
   5:     return new T() { DataContext = vm };
   6: }
   7:  
   8: private ViewModel GetViewModel(Type viewType)
   9: {
  10:     ViewModelAttribute attribute = 
  11:         viewType
  12:             .GetCustomAttributes(typeof(ViewModelAttribute), true)
  13:             .OfType<ViewModelAttribute>()
  14:             .SingleOrDefault();
  15:  
  16:     if (attribute == null)
  17:         throw new InvalidOperationException("Missing ViewModelAttribute");
  18:  
  19:     ViewModel vm = this.TheContainer.Resolve(attribute.ViewModelType) as ViewModel;
  20:  
  21:     if (vm == null)
  22:         throw new InvalidOperationException("Cannot Resolve ViewModel");
  23:  
  24:     return vm;
  25: }

Using the ViewBuilderService

It is time to use the service inside our applications. First of all we have to register the service into the IOC container. We can register the service like we already have registered the ViewModel using the RegisterType method. While we can use the same instance of the service in all the application we can use a ContainerControlledLifetimeManager. This type of lifetime manager will transform the service in a singleton instance.

   1: /// <summary>
   2: /// Registers the types.
   3: /// </summary>
   4: private void RegisterTypes()
   5: {
   6:     this.Container.RegisterType<IViewBuilderService, ViewBuilder>(
   7:         new ContainerControlledLifetimeManager());
   8:  
   9:     this.Container.RegisterType<IMyViewModel, MyViewModel>();
  10: }

Then now using the ServiceLocator we can discover the service when we need to create a View. The ServiceLocator is a Singleton class, that is capable to search registered types by its interface and return an instance. You can use the ServiceLocator everywhere you need to find the IViewBuilderService.  Here is the code to create a View and assign to the Shell:

   1: Grid grid = this.Shell.FindName("LayoutRoot") as Grid;
   2:  
   3: if (grid != null)
   4: {
   5:     IViewBuilderService vbs =
   6:         ServiceLocator.Current.GetInstance<IViewBuilderService>();
   7:  
   8:     MyView view = vbs.CreateView<MyView>();
   9:  
  10:     grid.Children.Add(view);
  11: }

Obviously I could use the RegionManager to put the new View into the user interface but I wanted to keep the example simple.

All the code I've tryied to explain in this post is attached at the end of the article. I hope you will find it useful in your applications and I will expect comments from you to improve my design and know your opinion about it.

Download: SilverlightPlayground.ViewBuilderService.zip (~430 kb)

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

Use CollectionViewSource effectively in MVVM applications

2009-07-18T23:13:15+01:00 by Andrea Boschin

In a my I've outlined the new CollectionViewSource introduced in silverlight with the latest release. This control is really useful while we need to sort and filter collection of objects in memory, but if we need to use a Model-View-ViewModel pattern to develop our application there is some problems using the control.

To implement the MVVM pattern we need to inject a ViewModel into the View using the DataContext property. This is usual in this kind of application because we need to bind the properties of the ViewModel to the controls in the View. So if we need to use a CollectionViewSource we can try to bind a collection from the ViewModel to the CVS and then bind the control to the CVS itself. Unfortunately this approach does not work because we cannot bind the CVS directly to the DataContext of the page. Trying to do this operation we will get a AG_E_BAD_PROPERTY_VALUE exception because the control does not inherits from FrameworkElement so it does not support DataBinding.

However, if it were possible, the CollectionViewSource would force us to put a lot of code in the codebehind to handle the Filter event and the sorting property. So, we have to follow another way to use the CollectionViewSource effectively with this kind of applications.

How to use the CollectionViewSource

The only way to use the CollectionViewSource with the MVVP pattern is to expose it as the type of the bindable property. This way we can manage the properties of the CVS and handle the Filter event from inside the ViewModel without putting anything in the codebehind of the View.

First of all we have to create two properties in the ViewModel. The first property will be the ObservableCollection<T> and we will populate it with the data to display. This property can be private because it will be used only to feed the ColectionViewSource of the second property. Here is how to initialize the properties:

   1: /// <summary>
   2: /// Gets or sets the names.
   3: /// </summary>
   4: /// <value>The names.</value>
   5: public CollectionViewSource Names { get; set; }
   6:  
   7: /// <summary>
   8: /// Gets or sets the names internal.
   9: /// </summary>
  10: /// <value>The names internal.</value>
  11: private ObservableCollection<string> NamesInternal { get; set; }
  12:  
  13: /// <summary>
  14: /// Initializes a new instance of the <see cref="MainPageViewModel"/> class.
  15: /// </summary>
  16: public MainPageViewModel()
  17: {
  18:     this.NamesInternal = new ObservableCollection<string>();
  19:     this.Names = new CollectionViewSource();
  20:     this.Names.Source = this.NamesInternal;
  21:  
  22:     // populate the ObservableCollection
  23:     foreach (string item in DataSource.GetNames())
  24:         this.NamesInternal.Add(item);
  25: }

Now, to bind the CollectionViewSource in the XAML we have to rely on his View property. If we put a reference to the CVS in the property ItemsSource in the XAML it simply will not work. Here is how to correctly bind:

   1: <ListBox ItemsSource="{Binding Names.View}" Margin="5,5,5,1" Grid.ColumnSpan="4" />

Once we have connected the CVS to the collection and the UI to the CVS we can handle the commands from the View and interact with the CVS to modify how to display the data. In the sample I have a togglebutton that is raising a ChangeSortDirectionCommand. I use the DelegateCommand<T> from Prism V2.0 and when someone send the command I change the SortDescriptor in the CollectionViewSource.

In the same View the TextChanged event is raised when the user type in the textbox. This command handled by the ViewModel let the CVS refresh itself. This way the Filter event will be evaluated again and the View will be updated with the filter applied.

I've attached to the post a new version of the sample I've proposed with the first article. Now the sample use the MVVM pattern with the CollectionViewSource.

Download: Elite.Silverlight3.CollectionViewMVVM.zip (~520 KB)

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

Silverlight 3.0 RTW: A new HTTP stack ready for REST

2009-07-10T17:45:00+01:00 by Andrea Boschin

The paradigm behind REST services is very fascinating while it allow to manipulate resources over the network relying to Uri and Http Methods. For a few of you that are not aware of what REST means I suggest to think at the web because it is the more REST thing you know. When you are pointing your browser to a "resource" on the Internet, for example a product in a ecommerce website, you will write an Url in the browser that univocally identify the product. You now can imagine to use Http Methods to operate on this resource: the GET verb will retrieve information about it, the PUT updates the resource, the POST creates it and finally the DELETE remove the resource from the web. In a few words these are REST operations and is very cool to be able to use this paradigm to access resources from a Database. ADO.NET Data Services is born to implement this paradigm into the .NET Framework 3.5 SP1, and many libraries has been build to support different technologies, Windows Forms, WPF, ASP.NET. And obviously Silverlight 2.0 come with an implementation of a Data Service client to operate with REST resources but it is not really RESTful as you may believe the first time you use it.

The problem with Silverlight 2.0, due to limitations to the http stack coming from the use of the Browser API, is that it cannot handle all the required http methods but only the GET and POST verbs. So to workaround this limitation the Data Service library simply use POST to send PUT and DELETE operations. This workaround violate the REST paradigm and it imply you are not able to use 3rd party REST resources.

What I've briefly explained in the previous paragraphs is the main reason we really need a new http stack to overcome this limitations and to be able to implement a full REST interface. This is not the only benefit we can give for the addition of new verbs: let think for example to a new way to upload files to the server, using the PUT method.

The latest release of Silverlight 3.0 got new features going in the direction I've just explained. In the next paragraphs I will explain how to use them by exploring the pretty new http Stack, called ClientHttp.

BrowserHttpStack vs ClientHttpStack

First of all we need to know that the new http stack is completely separated from the old stack. This is an important note while we are sure the old stack remain unaltered and our applications relaying on it continue to work without any change. All the working things we already know continue to work over this stack and does not use the new one.

The ClientHttpStack in opposite to the BrowserHttpStack (these are the official names of the two actors) can be created using a static class called WebRequestCreator. This class can create instances of HttpWebRequest for both the browser and the client stack. Here is a sample showing the usage of the class.

   1: // create an instance of the Client stack
   2: HttpWebRequest rq = (HttpWebRequest)WebRequestCreator.ClientHttp.Create(uri);
   3:  
   4: ...or...
   5:  
   6: // create an instance of the Browser stack
   7: HttpWebRequest rq = (HttpWebRequest)WebRequestCreator.BrowserHttp.Create(uri);

The HttpWebRequest created by this call is exactly the same we have used since Silverlight 2.0 so it can easily replace the browser stack in every existing application with a few line of code. We can immediately test the new stack assigning the Method property with the "PUT" value:

rq.Method = "PUT";

As we expect while the old stack thrown a "method not supported" exception, the new stack accept this assignment. Not all the http methods are allowed. Using TRACE, TRACK or CONNECT raise an error probably for security reasons. We will go deep inside some of the available methods in the next paragraph.

But this is only the most evident difference. Watching for the properties of the HttpWebRequest we will find a CookieContainer. It let us manage the cookies of the request. The old stack rely on cookies issued by the browser and it shares them with the browser itself. In the new stack we have full control of issued cookies; we can access cookies sent by the server or create our own cookies and send them. The drawback is that we cannot share cookies between client stack and browser stack but only rely on automatic management of server cookies from the client stack to allow forms authentication scenarios.

The next sample show how to use the CookieContainer to send our cookies:

   1: HttpWebRequest rq = (HttpWebRequest)WebRequestCreator.ClientHttp.Create(uri);
   2: rq.Method = "GET";
   3: rq.CookieContainer = new CookieContainer();
   4: rq.CookieContainer.Add(
   5:     uri, new Cookie("Author", "Andrea Boschin"));

Another great news, many people will really appreciate, is that the new stack is capable of retrieving status codes from the http response. One of the most common problems with Silverlight 2.0, especially the first time someone try to use the HttpWebRequest is the unability to get errors from the server. This is because the browser do not send all status codes to the plugins but only 404 (Not Found) and 200 (OK). The forum is filled of disoriented people not understanding why they get a 404 from the server while they are calling an existing uri and the most common suggestion is to use fiddler to search the error in the traced call.

To read status codes from the response we have to catch the WebException and then get the HttpWebResponse from the exception. This may seems a bit strange but is really simple. Here is the code:

   1: rq.BeginGetResponse(
   2:     r =>
   3:     {
   4:         try
   5:         {
   6:             WebResponse rs = rq.EndGetResponse(r);
   7:             // do something with response...
   8:         }
   9:         catch (WebException ex)
  10:         {
  11:             HttpWebResponse rs = (HttpWebResponse)ex.Response;
  12:  
  13:             MessageBox.Show(
  14:                 string.Format("Webserver returned status code {0}: '{1}'", 
  15:                     (int)rs.StatusCode, 
  16:                     rs.StatusDescription));
  17:         }
  18:     }, rq);

These features is really useful but they are not used from existing classes. WCF and WebClient can only use the classic http stack. To have access to the ClientHttpStack we have to use the HttpWebRequest and dealing with problems like thread syncronization that are solved by the WebClient. But the new stack is very important and now it is time to have some samples about usage of the http methods.

GET, POST, PUT & DELETE

In the sample solution attached at the end of this article I've enclosed a sort of file system browser application. It use the new http stack to make calls to the server and retrieve xml containing the response. This kind of application was possible also with Silverlight 2.0 but to explaing usage of http methods I've used them to mimic some filesystem operations. GET will list the content of a folder, PUT upload a file or create a directory, POST is used to send credentials and finally DELETE remove files and directories.

Doing an http call is very similar to using the previous stack. We need to create an instance of the stack, set the method we want to use and then create a request as the server will expect it. The following sample make a call to get the directory content. I've splitted the operations in two methods, one doing the raw http call and the other using this low-level method create the request and parse the result. This is the low-level DoGet() method:

   1: private static void DoGet(Uri uri, Action<Stream> success, Action<Exception> fail)
   2: {
   3:     try
   4:     {
   5:         HttpWebRequest rq = (HttpWebRequest)WebRequestCreator.ClientHttp.Create(uri);
   6:         rq.Method = "GET";
   7:         rq.CookieContainer = new CookieContainer();
   8:         rq.BeginGetResponse(
   9:             new AsyncCallback(
  10:                 r =>
  11:                 {
  12:                     try
  13:                     {
  14:                         WebResponse rs = rq.EndGetResponse(r);
  15:                         success(rs.GetResponseStream());
  16:                     }
  17:                     catch (WebException ex)
  18:                     {
  19:                         fail(CreateFailFromWebException(ex));
  20:                     }
  21:                 }), null);
  22:     }
  23:     catch (Exception ex)
  24:     {
  25:         fail(ex);
  26:     }
  27: }

The code in this listing shows the usual way to place an http call. First of all the DoGet method require I specify two callback methods to be called when the request will succeed or fail. This pattern helps to simplify the code to write avoiding handling multiple event handler. Using lambda expressions the code become very compact.

After the creation of the client stack I initialize the "Method" property with the GET verb, then I create an instance of a CookieContainer to allow the request to handle cookies. Finally calling BeginGetResponse place the call to the specified uri. When this method is called a new thread is created; In my case the body of the inner lambda expression contains the code executed in the thread. It call the EndGetResponse method (this trigger the call to the webserver) and finally ask for the Stream containing the body of the response.

As I explain in the previous paragraph I have to catch the WebException to read http status codes and translate it to an call to the fail() callback. You have to be aware that the two try-catch blocks are executed in different threads so the external block is unable to catch exception coming from the body of the lambda expression. This is the reason for having two separated blocks calling the fail method. Now watch to the following code:

   1: public static void GetDirectory(string path, Action<FileSystemItem[]> success, Action<Exception> fail)
   2: {
   3:    Uri uri = new Uri(
   4:        DataSource.ServiceUri +
   5:        "?action=directory" +
   6:        "&path=" + HttpUtility.UrlEncode(path));
   7:  
   8:    DataSource.DoGet(uri,
   9:        r =>
  10:        {
  11:            try
  12:            {
  13:                XDocument document = XDocument.Load(r);
  14:                IEnumerable<FileSystemItem> directories = DataSource.DeserializeItems(document);
  15:                Deployment.Current.Dispatcher.BeginInvoke(() => success(directories.ToArray()));
  16:            }
  17:            catch (Exception ex)
  18:            {
  19:                Deployment.Current.Dispatcher.BeginInvoke(() => fail(ex));
  20:            }
  21:        },
  22:        e => Deployment.Current.Dispatcher.BeginInvoke(() => fail(e)));
  23: }

This is the high-level method to get the directory content.  It use the same asyncronous pattern but maps the calls to the callback methods to the UI thread using an instance of the Dispatcher. While the HttpWebRequest make the calls in a different thread we need to marshal the context of the call to avoid cross-thread exception when we try to reach some UI components.

Using PUT to upload a file

Showing all the methods one-by-one is too much long. But there are another (last)  method I want to show. It is the PUT method we can use to upload files to a webserver in an alternate (and most simple) way to the use of the POST method. While the POST method require encoding the resource to base64 and forge a complex request, the PUT method simply ask to enqueue the full binary content. Here is the client code:

   1: private static void DoPut(Uri uri, FileStream file, Action<Stream> success, Action<Exception> fail)
   2: {
   3:     try
   4:     {
   5:         HttpWebRequest rq = (HttpWebRequest)WebRequestCreator.ClientHttp.Create(uri);
   6:         rq.Method = "PUT";
   7:         rq.CookieContainer = DataSource.Cookies;
   8:         rq.BeginGetRequestStream(
   9:             new AsyncCallback(
  10:                 result => DataSource.DoPutUpload(result, file, success, fail)), rq);
  11:     }
  12:     catch (Exception ex)
  13:     {
  14:         fail(ex);
  15:     }
  16: }
  17:  
  18: private static void DoPutUpload(IAsyncResult result, FileStream file, Action<Stream> success, Action<Exception> fail)
  19: {
  20:     HttpWebRequest rq = (HttpWebRequest)result.AsyncState;
  21:  
  22:     using (Stream stream = rq.EndGetRequestStream(result))
  23:     {
  24:         int read = 0;
  25:         byte[] buffer = new byte[1024];
  26:  
  27:         while ((read = file.Read(buffer, 0, buffer.Length)) > 0)
  28:             stream.Write(buffer, 0, read);
  29:     }
  30:  
  31:     rq.BeginGetResponse(
  32:         r =>
  33:         {
  34:             try
  35:             {
  36:                 WebResponse rs = rq.EndGetResponse(r);
  37:                 success(rs.GetResponseStream());
  38:             }
  39:             catch (WebException ex)
  40:             {
  41:                 fail(CreateFailFromWebException(ex));
  42:             }
  43:         }, rq);
  44: }

The first method (DoPut) is very close to the previous method I described. The core of the upload is the DoPutUpload. It open a stream in the HttpWebRequest and write the entire content of the file to upload just before calling the EndGetRequest. When this call is made the file is send on the network to the webserver. I use an httphandler and when the PUT is receives read from the InputStream the file I write to the filesystem.

   1: private void ProcessFileRequest(string path)
   2: {
   3:     this.EvaluateIsValidUser();
   4:  
   5:     if (File.Exists(path))
   6:         throw new Exception("File already exists");
   7:  
   8:     using (FileStream stream = File.OpenWrite(path))
   9:     {
  10:         byte[] data = new byte[1024];
  11:         int read = 0;
  12:  
  13:         while ((read = this.Context.Request.InputStream.Read(data, 0, 1024)) > 0)
  14:             stream.Write(data, 0, read);
  15:     }
  16:  
  17:     this.WriteOk();
  18: }

The last code runs on the server. It receive the path of the file to write and create it in the file system. The final WriteOk() method show I can write something on the response to notify the client it have successful uploaded the file.

Some final words

The main benefit coming with the introduction of the new stack is the opportunity to be able to get access to rest resources on the internet. This is the reason for the creation of this stack someone can consider a duplication on something already exists. But the presence of new methods, the cabapility to better handle server status codes and cookies give to Silverlight 3.0 a new resource to implement great applications.

The code I attached to this article show a full implementation of all the http methods I've talk about. You have only to change the server path where the filesystem has to be explored. You can achive this by changing the BaseFolder property in the HttpRequestManager class.

Download: Elite.Silverlight3.ClientHttpStack.zip (2,1 MB)

Video: ClientHTTPStack.wmv (10,1 MB)

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

What's new about Out Of Browser in Silverlight 3.0 RTW

2009-07-10T17:45:00+01:00 by Andrea Boschin

Some months ago, a couple of minutes after the first beta of Silverlight has been released, I've posted an article explaining how to configure the new Out of Browser feature in Silverlight 3.0. Now, just after the release of the final bits, I need to return back on the argument because something has changed during this time due to additional features and modification to the API I've explained.

What has changed and What has been added.

There is not any substantial change to the functionality of the OOB applications. As you may expect it is still available a context menu to detach the application from the browser - but this operation now has changed its name from "detach" to "install" - and there is a way to uninstall the application again with the same context menu. While the name of the operation has changed now the method and events related to is has also changed the name following this schema:

Previous Current
public bool Detach(); public bool Install();
public bool RunningOffline; public bool RunningOutOfBrowser;
public event EventHandler ExecutionStateChanged; public event EventHandler InstallStateChanged;
public enum ExecutionStates
{
    RunningOnline,
    Detaching,
    Detached,
    DetachedUpdatesAvailable,
    DetachFailed
}
public enum InstallState
{
    NotInstalled,
    Installing,
    Installed,
    InstallFailed
}


As you may have noticed one important enumeration member - DetachedUpdatesAvailable - has been removed but this feature has not been lost. Now there a couple of API to support the application updates giving a bit more control in the update flow. We can choice when check for updates using the CheckAndDownloadUpdateAsync() method and getting notified if the update process succeded by the event CheckAndDownloadUpdateCompleted. Here is how to check for updates:

   1: Application.Current.CheckAndDownloadUpdateCompleted +=
   2:     (s, e) =>
   3:     {
   4:         if (e.UpdateAvailable)
   5:             MessageBox.Show(@"Updates have been downloaded. 
   6:                               Please restart the application to 
   7:                               apply this updates.");
   8:     };
   9:  
  10: Application.Current.CheckAndDownloadUpdateAsync();

Once you have started the process there isn't any way to stop it or to rollback any downloaded update. You can only notify the user that the updates has been downloaded and that this updates will be available the next time the application will be started.

The most significant change to the Out-of-browser is in the feature configuration. Now the settings are placed in a specific file you can find into the Properties folder in the Solution Explorer. The file OutOfBrowserSettings.xml contains the same properties of the beta with some slight changes:

1. The Title property has been moved to the WindowSettings section
2. Width and Height properties has been added to configure the initial size of the window
3. The Icon size has to be specified using a comma separated value notation

Now Visual Studio 2008 can directly manage this properties using an Out-of-Browser Settings button in the Silverlight properties tab so there is no need to directly edit the xml file.

Out of browser configuration You have to be aware that there is not full control over plugin features while it is installed on the machine. The sole feature you can activate i the usage of GPU acceleration, but there isn't a way to change the backgroun color of the plugin. Also remember that the usage of html bridge is forbidden while in oob mode.

Updated Sample

I've just changed the downloadable sample attached to my previous article and I give you agan the link here to have a fully functional sample on how to configure and use the out of browser.

Download code: Elite.Silverlight3.ToDoList.zip (2.02 MB)

Demo Video: OutOfBrowserExperience.wmv (3.5 MB)

Silverlight 3.0 RTW: An universal MouseWheelScrolling behavior

2009-07-10T17:45:00+01:00 by Andrea Boschin

Silverlight 3.0 RTW introduces a new event many people has asked for in the last months, the MouseWheel event. Handling this event is pretty simple while it simply raise and event that take a Delta to the developer with a positive or negative value according to the direction and the amount of the scrolling.

Showing an sample about MouseWheel take a few lines of code and is unuseful while I think many people can simply experiment and understant how it works in a few minutes. So I decided to merge this sample with some words about the new Behaviors introduced with Expression Blend.

My focus in this post is to show how to create a Behavior,  and using the MouseWheel event, add to all the scrollable controls the capability to scroll using the Mouse wheel.

What is a Behavior?

Some of you may have already used the Behaviors in the ASP.NET AJAX framework. The simple answer to the question of this paragraph is: "They are a Silverlight implementation of the ASP.NET AJAX semantics that allow to create reusable and attachable behaviors to HTML controls". You may find the origin of Silverlight Behaviors in an example posted by Nikhil Kothari during the May 2008.

While the simple answer is very clear and let you understand the concept under Behaviors we have to explore them more deeply to understant how to create a behavior and let it available to our projects.

The beta of Blend 3 introduces the concept of behavior into the Blend interface. There are some built-in behaviors we can simply drag on the design surface to give a new life to our graphical elements. Into the Asset folder, where usually we find controls, effects, resources and other thing, there is a new "behaviors" sheet like in the image I attached here on the right. 

With Expression Blend 3.0 many types of behaviors have been introduced. Behavior<T> is the most simple flavour that apply to a DependencyObject (the generic T) and handle events and other aspects from the source controls. A behavior can simply modify the aspect of a control, adding elements, changing the properties, or can handle one or more events to add some new features. The MouseDragElementBehavior is an example of it. Simply it attach Mouse events and let the element to be dragged into the page.

Writing a behavior

Writing a behavior is a pretty simple task. A behavior is a class extending Behavior<T> so the first thing to do is referencing the assemblies Microsoft.Expression.Interactions.dll and System.Windows.Interactivity.dll. from the following folder:

C:\Program Files\Microsoft SDKs\Expression\Blend 3\Interactivity\Libraries\Silverlight

If you add an existing behavior from Blend 3.0 a reference to these assemblies is automatically added to your project.

Once you have added the reference it is time to create the class:

   1: public class MouseWheelScrollBehavior : Behavior<Control>
   2: {
   3:     // Add implementation here
   4: }

While we are extending the "scrollable" components in Silverlight we need to create a type that can be attached to Control classes. In silverlight there is not any common class to scrollable components like ScrollViewer, DataGrid and ListBox. This imply we have to find a way to scroll eterogeneous components, but this is matter for the next paragraph. For now simply continue to analyze how to create the Behavior.

The next thing to do is to attach the MouseWheel event on the target object. Once we have extended the Behavior class we have two methods to override useful to handle attach and detach of the behavior to the target: OnAttached is called when the behavior attach an object and OnDetaching when it is detaching from the object. OnAttached and OnDetaching is the perfect location to attach and detach public events that we will handle to give the behavior to the target object. Obviously the target object is exposed by the Behavior<T> in the AssociatedObject property. Here is my code sample:

   1: /// <summary>
   2: /// Called after the behavior is attached to an AssociatedObject.
   3: /// </summary>
   4: /// <remarks>Override this to hook up functionality to the AssociatedObject.</remarks>
   5: protected override void OnAttached()
   6: {
   7:     this.AssociatedObject.MouseWheel += new MouseWheelEventHandler(AssociatedObject_MouseWheel);
   8:     base.OnAttached();
   9: }
  10:  
  11: /// <summary>
  12: /// Called when the behavior is being detached from its AssociatedObject, but before it has actually occurred.
  13: /// </summary>
  14: /// <remarks>Override this to unhook functionality from the AssociatedObject.</remarks>
  15: protected override void OnDetaching()
  16: {
  17:     this.AssociatedObject.MouseWheel -= new MouseWheelEventHandler(AssociatedObject_MouseWheel);
  18:     base.OnDetaching();
  19: }

Now the behavior is ready to be attached to the object but it still does nothing. We need to implement the scrolling for scrollable components, so it is time to enter the next paragraph.

Scrolling the Scrollable... not so simple!

While I'm writing the sample I've attached to this post, there were a moment when I thinked this behavior is impossible to be implemented and I was ready to switch to a less generic ScrollViewer scroller behavior. The reason for this is that there is not any common scrolling interface to scrollable components. So while creating a Behavior for a ScrollViewer is simple, it is not so simple to use it for DataGrid or ListBox.

Just a moment before discarting my sample I've gived a last chance to "bing" to find someone handling the same problem. I finally found this that explain how to use Automation API in Silverlight to enable the scrolling of components without extending them.

I leave the full explanation to the good article I've linked. Here the only thing we need to Know is that Automation API expose a IScrollProvider interface doing exactly what I'm searching for. So we need to change the OnAttached method to create the Automation Peer for the attaching object:

   1: /// <summary>
   2: /// Gets or sets the peer.
   3: /// </summary>
   4: /// <value>The peer.</value>
   5: private AutomationPeer Peer { get; set; }
   6:  
   7: /// <summary>
   8: /// Called after the behavior is attached to an AssociatedObject.
   9: /// </summary>
  10: /// <remarks>Override this to hook up functionality to the AssociatedObject.</remarks>
  11: protected override void OnAttached()
  12: {
  13:     this.Peer = FrameworkElementAutomationPeer.FromElement(this.AssociatedObject);
  14:  
  15:     if (this.Peer == null)
  16:         this.Peer = FrameworkElementAutomationPeer.CreatePeerForElement(this.AssociatedObject);
  17:  
  18:     this.AssociatedObject.MouseWheel += new MouseWheelEventHandler(AssociatedObject_MouseWheel);
  19:     base.OnAttached();
  20: }

First we search the Automation interfaces if the control already created it. If the interface has not been found we need to create it. The AutomationPeer is saved in a member property to be used when the MouseWheel event is raised. Here is the code to scroll the target:

   1: /// <summary>
   2: /// Handles the MouseWheel event of the AssociatedObject control.
   3: /// </summary>
   4: /// <param name="sender">The source of the event.</param>
   5: /// <param name="e">The <see cref="System.Windows.Input.MouseWheelEventArgs"/> instance containing the event data.</param>
   6: void AssociatedObject_MouseWheel(object sender, MouseWheelEventArgs e)
   7: {
   8:     this.AssociatedObject.Focus();
   9:  
  10:     int direction = Math.Sign(e.Delta);
  11:  
  12:     ScrollAmount scrollAmount = 
  13:         (direction < 0) ? ScrollAmount.SmallIncrement : ScrollAmount.SmallDecrement;
  14:  
  15:     if (this.Peer != null)
  16:     {
  17:         IScrollProvider scrollProvider =
  18:             this.Peer.GetPattern(PatternInterface.Scroll) as IScrollProvider;
  19:  
  20:         bool shiftKey = (Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift;
  21:  
  22:         if (scrollProvider != null && scrollProvider.VerticallyScrollable && !shiftKey)
  23:             scrollProvider.Scroll(ScrollAmount.NoAmount, scrollAmount);
  24:         else if (scrollProvider != null && scrollProvider.VerticallyScrollable && shiftKey)
  25:             scrollProvider.Scroll(scrollAmount, ScrollAmount.NoAmount);
  26:     }
  27: }

When we get the Delta we need to extract the direction of the scrolling. This is because we are unable to speficy the amount of pixels we have to scroll the target but simply the ScrollAmount that may be a SmallIncrement or SmallDecrement (or LargeIncrement, LargeDecrement). So using the direction we decide from Increment and Decrement.

While the controls can scroll both vertically or horizontally I decided to check if the shift key is pressed to allow horizontal scroll. Finally using the Scroll method in the IScrollProvider I apply the scrolling to the target control. This is very simple because the IScrollProvider does all the work for us. There is no need to check boundaries, we have simply to say how to scroll and all the work is done.

Using the Behavior

Using Blend is the simpler way to apply behaviors. The blend assets library scan the classes of the project and show them in the library so dragging the behavior on the scrollable component is sufficient to apply the behavior. We need to learn ho to apply the behavior by code. Here is a sample:

   1: <UserControl
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
   4:     xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 
   5:     xmlns:local="clr-namespace:Elite.Silverlight3.MouseWheelSample.Silverlight.Classes"
   6:     xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"
   7:     x:Class="Elite.Silverlight3.MouseWheelSample.Silverlight.MainPage" 
   8:     Width="Auto" Height="Auto">
   9:  
  10: ... omissis ...
  11:  
  12: <data:DataGrid Grid.Column="1" Grid.Row="0" ItemsSource="{Binding DataItems}" Margin="20">
  13:     <i:Interaction.Behaviors>
  14:         <local:MouseWheelScrollBehavior />
  15:     </i:Interaction.Behaviors>
  16: </data:DataGrid>

In the UserControl we declare the namespaces we have to use. In this sample "i" stand for interactivity, the assembly where the Behavior<T> classe is located. The "local" refer to the local classes where we put the new Behavior. In the second part we attach the behavior to a DataGrid. To attach the behavior to a ScrollViewer or to a ListBox the code is pretty similar. Running the project we will have the mouse wheel working on the DataGrid.

Conclusion

The tecnique I've illustrated has the big advantage or working for all the scrollable controls but not for ComboBox because it does not directly implements IScrollProvider interface. The drawback is that it works only on windows. This is a big problem but there is not any solution to it while as I already said it is the only way to scroll all the controls programmatically. Moreover we have to take note that the MouseWheel event only works in Windows with Internet Explorer and also with Firefox when you are not using the windowless mode. This is a limitation of the architecture of Safari and Firefox and the only way to work around it is using the DOM events. So due to this limitations the example is a good solution to be used where it works. In the others cases it simply does nothing.

Download: Elite.Silverlight3.MouseWheelSample.zip (1,2 MB)

Video: MouseWheelScrollBehavior.wmv (1.4 MB)

Silverlight 3.0 RTW: The CollectionViewSource

2009-07-10T17:45:00+01:00 by Andrea Boschin

Since the first release of WPF the framework contains a component called CollectionViewSource. The CollectionViewSource allow developer to apply sorting, filtering and grouping to in-memory collections of objects. This component is very useful when small collections (up to hundreds of items) is loaded in memory and need to give a better experience to the user.

Some months ago I of the CollectionViewSource for Silverlight 2.0. I worked hard to implement the component and finally I published a version with the only limitation of not allowing grouping. While sorting and filtering are implemented directly on the data seamless, the grouping require an infrastructure to be consumed (grouping support in ItemsControl) that I was unable to provide.

The new release of Silverlight 3.0 RTW comes with an implementation of this component that fill this hole but it has the same limitations of my CollectionViewSource. This limitations come from the same reason I cannot implement by myself: the missing grouping support in ItemsControls. However the native component has a some advantages on mine, first of all a very strict compatibility with the architecture of the WPF CollectionViewSource. In this post I will show you how to configure and use the component in a Silverlight application.

Using the CollectionViewSource

The Silverlight CollectionViewSource is a class that inherits from DependencyObject and usually can be inserted in a resource dictionary in the page where it has to work. The principle of the CVS (this is the shorter name I will use from this point in advace) is acting as a filter between the source collection (IEnumerable or IList) and the component where we are showing the data. While binding a ListBox directly to a flat collection will show all the instances in the collection, putting the CVS in the middle enable us to operate on its properties to sort and filter the source.

Here is an example that shows how to embed the CVS in a xaml page; The first part show a DataSource object SampleDataCollection in the UserControl.Resources, and a CollectionViewSource that reference it using StaticResource. In the second part there is a ListBox that reference the CVS also using a StaticResource markup extension.

   1: ... omissis ...
   2:  
   3: <UserControl.Resources>
   4:     <local:DataSource x:Key="dataSource" />
   5:     <CollectionViewSource x:Name="cvs" Source="{Binding Names, Source={StaticResource dataSource}}">
   6:         <CollectionViewSource.SortDescriptions>
   7:             <scm:SortDescription Direction="Ascending" />
   8:         </CollectionViewSource.SortDescriptions>
   9:     </CollectionViewSource>
  10: </UserControl.Resources>
  11:  
  12: ... omissis ...
  13:  
  14: <ListBox ItemsSource="{Binding Source={StaticResource cvs}}" 
  15:          Margin="5,5,5,1" Grid.ColumnSpan="4" />
  16:  
  17: ... omissis ...

The magic around CVS come from an interface called ICollectionView that is esposed by the CVS in the View property. This interface represent the real working object that behind the scenes understand the source type and manage to apply filtering and sorting seamless. When a datasource is connected to the CVS a specialized instance of the ICollectionView is created - EnumerableCollectionView for IEnumerable or ListCollectionView for IList - and this instance work knowing the source data. When we connect a consumer control to the CVS it is binded directly to the ICollectionView. Watching at this interface we will see it implements INotifyCollectionChanged. This mean that if we connect the CVS to an ObservableCollection<T> all the updates to the source collection will be transmitted to the consumer.

Sorting and Filtering

Now after the basics of the CVS it is time to try to use its properties to apply the features it implements. If we see at the CVS we will see a Filter event exposed to the markup or to the code. This event is raised by the CVS every time it need to understand if an item of the collection is valid for the filter the user is appling. In the semple I included at the end of this post I use the CVS to filter a collection of italian names (strings). In the Filter event I simply compare every item in the collection to the letters the use typed in a TextBox:

   1: /// <summary>
   2: /// Handles the Filter event of the cvs control.
   3: /// </summary>
   4: /// <param name="sender">The source of the event.</param>
   5: /// <param name="e">The <see cref="System.Windows.Data.FilterEventArgs"/> instance containing the event data.</param>
   6: void cvs_Filter(object sender, FilterEventArgs e)
   7: {
   8:     e.Accepted = ((string)e.Item).ToLower().StartsWith(searchKey.Text.ToLower());
   9: }

The FilterEventArgs class expose an Accepted property useful to indicate if the element (e.Item) we are evaluating has to be shown or not. This event is very simple to handle and let the developer to apply various filtering rules. We have only to pay attention to the time that the evaluation take because it is repeated one time for every element in the collection.

While the user type in the TextBox we catch the TextChanged event and force the refresh of the CVS this way:

   1: /// <summary>
   2: /// Handles the TextChanged event of the searchKey control.
   3: /// </summary>
   4: /// <param name="sender">The source of the event.</param>
   5: /// <param name="e">The <see cref="System.Windows.Controls.TextChangedEventArgs"/> instance containing the event data.</param>
   6: private void searchKey_TextChanged(object sender, TextChangedEventArgs e)
   7: {
   8:     this.cvs.View.Refresh();
   9: }

Applying sorting if simpler than filtering. It is done by using markup with the SortDescriptions property. This property accept a collection of SortDescription, one for every property we need to sort. For each property we can choice the direction of sorting using the Direction property:

<scm:SortDescription Direction="Ascending" PropertyName="Name" />

Here is a snippet of code from the sample i provide:

   1: <CollectionViewSource x:Name="cvs">
   2:     <CollectionViewSource.SortDescriptions>
   3:         <scm:SortDescription Direction="Ascending" />
   4:     </CollectionViewSource.SortDescriptions>
   5: </CollectionViewSource>

While I'm binding strings there is no need to specify a property because the sort has to be applied directly to the source string. If you need a more complex sorting logic it is always available the IComparable interface that is used to evaluate the elements during the sort operation.

Differences from WPF

While at the first look the CollectionViewSource implementation in Silverlight appear to be very close to the WPF component, there is some subtle differences. First of all if we examine the component we may found a property called GroupDescriptions. This property is used in WPF to apply grouping but in the Silverlight version it throw a NotSupportedException. Probably it is a placeholder for future extensions of the component.

The most important difference to me if about the structure of the object. The CVS inherits from DependencyObject but while in silverlight only classes derived from FrameworkElement may be subject of DataBinding the only way to put a CVS in markup would be using a StaticResource.

This would be a huge limitation to CVS but fortunately the people from the team found a way to workaround it. Also if CVS inherits from DependencyObject it is still possible to use databinding but it is needed to specify an explicit Source like the following example:

   1: <UserControl.Resources>
   2:     <CollectionViewSource x:Name="cvs" Source="{Binding Names, Source={StaticResource dataSource}}">
   3:         <CollectionViewSource.SortDescriptions>
   4:             <scm:SortDescription Direction="Ascending" />
   5:         </CollectionViewSource.SortDescriptions>
   6:     </CollectionViewSource>
   7: </UserControl.Resources>

This is very useful if we have a complex object like a ViewModel we want to use in a page with a CVS instance. The better would be to bind directly to the datasource but is is possible to put the ViewModel in the resources and then statically reference it from both the DataContext and the CollectionViewSource.

Conclusion

Last months I decided to start writing a component like CVS because I think it is really useful in some cases. Now I'm very glad to rely on a framework component. For some of you that have been used my component take note that the CVS interface is very close to my component so it is very easy to switch to it.

Download: Elite.Silverlight3.CollectionViewSample.zip (1,04 MB)

Video: CollectionViewSource.wmv (1.08 MB)

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

A code snippet to quickly write Prism commands

2009-07-09T22:16:53+01:00 by Andrea Boschin

Crawling the Internet there are many samples about how to write commands for the Composite Application Guidance, aka Prism v2.0. One of my favorites is the .

I figure out the first time you see how many code you need, to write a working command you are really astonished. This also happened to me. But if you analyze the code you will see that the skeleton of a command is always the same, and you need to change only some names and types to have it working on different events.

This is the perfect situation where a code snippet works effectively so I decided to write my own and publish on this site. I've isolated some zones you have to replace and I've created some markers that will take advantage of the Visual Studio expansion snippets.

  1. command: the name of the command you are writing (e.g. MouseOver)
  2. control: the control type your command apply to (e.g. Button)
  3. event: the event of the control your command will wrap


Here is the snippet:

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
   3:     <CodeSnippet Format="1.0.0">
   4:         <Header>
   5:             <Title>prismcommand</Title>
   6:             <Shortcut>prismcommand</Shortcut>
   7:             <Description>Code snippet for an automatically implemented commands</Description>
   8:             <Author>Elite Agency</Author>
   9:             <SnippetTypes>
  10:                 <SnippetType>Expansion</SnippetType>
  11:             </SnippetTypes>
  12:         </Header>
  13:         <Snippet>
  14:             <Declarations>
  15:                 <Literal>
  16:                     <ID>command</ID>
  17:                     <ToolTip>Command Name</ToolTip>
  18:                     <Default>CommandName</Default>
  19:                 </Literal>
  20:                 <Literal>
  21:                     <ID>control</ID>
  22:                     <ToolTip>Control type</ToolTip>
  23:                     <Default>Control</Default>
  24:                 </Literal>
  25:         <Literal>
  26:           <ID>event</ID>
  27:           <ToolTip>Control Event</ToolTip>
  28:           <Default>Event</Default>
  29:         </Literal>
  30:       </Declarations>
  31:             <Code Language="csharp">
  32:         <![CDATA[public class $command$CommandBehavior : CommandBehaviorBase<$control$>
  33:     {
  34:         public $command$CommandBehavior($control$ targetObject)
  35:             : base(targetObject)
  36:         {
  37:             targetObject.$event$ += (s, e) => base.ExecuteCommand();
  38:         }
  39:     }
  40:  
  41:     public static class $command$
  42:     {
  43:         public static readonly DependencyProperty $command$BehaviorProperty =
  44:             DependencyProperty.RegisterAttached(    
  45:                 "$command$BehaviorProperty", typeof($command$CommandBehavior), 
  46:                 typeof($command$CommandBehavior), null);
  47:  
  48:         #region CommandProperty
  49:  
  50:         public static readonly DependencyProperty CommandProperty =
  51:             DependencyProperty.RegisterAttached(
  52:                 "Command", typeof(ICommand), typeof($command$),
  53:                 new PropertyMetadata(CommandProperty_Changed));
  54:  
  55:         public static ICommand GetCommand(DependencyObject obj)
  56:         {
  57:             return (ICommand)obj.GetValue(CommandProperty);
  58:         }
  59:  
  60:         public static void SetCommand(DependencyObject obj, ICommand value)
  61:         {
  62:             obj.SetValue(CommandProperty, value);
  63:         }
  64:  
  65:         private static void CommandProperty_Changed(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
  66:         {
  67:             $control$ targetObject = dependencyObject as $control$;
  68:  
  69:             if (targetObject != null)
  70:                 GetOrCreateBehavior(targetObject).Command = e.NewValue as ICommand;
  71:         }
  72:  
  73:         #endregion
  74:  
  75:         #region CommandParameterProperty
  76:  
  77:         public static readonly DependencyProperty CommandParameterProperty =
  78:             DependencyProperty.RegisterAttached(
  79:                 "CommandParameter", typeof(object), 
  80:                 typeof($command$), new PropertyMetadata(CommandParameterProperty_Changed));
  81:  
  82:         public static ICommand GetCommandParameter(DependencyObject obj)
  83:         {
  84:             return (ICommand)obj.GetValue(CommandParameterProperty);
  85:         }
  86:  
  87:         public static void SetCommandParameter(DependencyObject obj, ICommand value)
  88:         {
  89:             obj.SetValue(CommandParameterProperty, value);
  90:         }
  91:  
  92:         private static void CommandParameterProperty_Changed(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
  93:         {
  94:             $control$ targetObject = dependencyObject as $control$;
  95:  
  96:             if (targetObject != null)
  97:                 GetOrCreateBehavior(targetObject).CommandParameter = e.NewValue;
  98:         }
  99:  
 100:         #endregion
 101:         
 102:         private static $command$CommandBehavior GetOrCreateBehavior($control$ targetObject)
 103:         {
 104:             $command$CommandBehavior behavior = targetObject.GetValue($command$BehaviorProperty) as $command$CommandBehavior;
 105:  
 106:             if (behavior == null)
 107:             {
 108:                 behavior = new $command$CommandBehavior(targetObject);
 109:                 targetObject.SetValue($command$BehaviorProperty, behavior);
 110:             }
 111:  
 112:             return behavior;
 113:         }
 114:     }]]>
 115:             </Code>
 116:         </Snippet>
 117:     </CodeSnippet>
 118: </CodeSnippets>

To have this snipped installed you simply need to create a file named prismcommand.snipped and copy the code inside it (or simply download the attached file). This file has to be loaded in the My Code Snippets directory using the Code Snippet Manager in Visual Studio 2008.

Finally after creating a file in your project type "prismcommand" in the text editor and hit TAB. Two classes will be exploded and you will be asked to provide the expansion tags I listed above. Obviously you have to include the assemblies from Prism and reference the Microsoft.Practices.Composite.Presentation.Commands namespace to have it compile.

Download:

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

New articles are close to launch...

2009-07-07T01:04:55+01:00 by Andrea Boschin

logo After a long period of silence I'm close to publish some new articles. While I'm very busy in the last months I was unable to write additional content. I preferred to stop publishing instead of writing something of fast and low in quality.

Now the workload is going down to a normal level so I have time to work on something new and it will be published very, very soon...

Please be patient.

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