Archive

Archive for the ‘WPF’ Category

Command Behaviours

June 29th, 2009

One of the challenges I have found when using MVVM in Prism, is that out of the box it only supports the click event. Luckily there is an extensibility point here using the CommandBehaviourBase class which means we can tie command execution to any event the control can raise and then bind this using an attached property in the XAML.

There are 3 parts to the code – the example I am going to use is the SelectionChanged event of the ListBox control.

namespace PrismExtension.CommandBehaviours
{
  public class SelectedChangedBehaviour : CommandBehaviorBase<listbox>
  {
     public SelectedChangedBehaviour(ListBox element) : base(element)
     {
        element.SelectionChanged += new SelectionChangedEventHandler(element_SelectedChanged);
      }

      private void element_SelectedChanged(object sender, SelectionChangedEventArgs e)
      {
        base.ExecuteCommand();
      }
    }
}



This code is pretty simple in what it does. The constructor takes an instance of the control you want to attach the event handling code to. The event handling code then executes the command when the event you are watching for is fired. The next part is a bit more tricky.


In order to get this into the XAML as an attached property we need to create a static class.

namespace PrismExtension.CommandBehaviours
{
  public static class SelectedChanged
  {      
     public static ICommand GetCommand(DependencyObject obj)
     {            
        return (ICommand)obj.GetValue(CommandProperty);        
     }          

     public static void SetCommand(DependencyObject obj, ICommand value)        
     {            
        obj.SetValue(CommandProperty, value);        
     }          

     public static readonly DependencyProperty CommandProperty = DependencyProperty.RegisterAttached("Command", typeof(ICommand), typeof(SelectedChanged), new PropertyMetadata(OnSetCommandCallback));          

     public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.RegisterAttached("CommandParameter",typeof(object),typeof(SelectedChanged), new PropertyMetadata(OnSetCommandParameterCallback));          

      private static void OnSetCommandCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)        
      {            
          ListBox element = dependencyObject as ListBox;            
          if (element != null)
          {                
              SelectedChangedBehaviour behavior = GetOrCreateBehavior(element);                          
              behavior.Command = e.NewValue as ICommand;            
           }
     }          

     public static void SetCommandParameter(ListBox listbox, object parameter)
     {            
          listbox.SetValue(CommandParameterProperty, parameter);        
      }        

      public static object GetCommandParameter(ListBox listbox)
      {            
          return listbox.GetValue(CommandParameterProperty);        
      }          

      private static SelectedChangedBehaviour GetOrCreateBehavior(ListBox element)
      {            
          SelectedChangedBehaviour behavior = element.GetValue(SelectedIndexChangedBehaviourProperty) as SelectedChangedBehaviour;            
           if (behavior == null)            
           {                
               behavior = new SelectedChangedBehaviour(element);                    
               element.SetValue(SelectedIndexChangedBehaviourProperty, behavior);            
            }
            return behavior;        
       }

       private static void OnSetCommandParameterCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)        
       {            
           ListBox listbox = dependencyObject as ListBox;            
           if (listbox != null)            
           {                
                 SelectedChangedBehaviour behavior = GetOrCreateBehavior(listbox);
                 behavior.CommandParameter = e.NewValue;            
           }        
        }          

         public static SelectedChangedBehaviour GetSelectedIndexChangedBehaviour(DependencyObject obj)    
         {            
             return (SelectedChangedBehaviour)obj.GetValue(SelectedIndexChangedBehaviourProperty);        
         }

          public static void SetSelectedIndexChangedBehaviour(DependencyObject obj, SelectedChangedBehaviour value)        
          {            
             obj.SetValue(SelectedIndexChangedBehaviourProperty, value);        
          }

          public static readonly DependencyProperty SelectedIndexChangedBehaviourProperty =             DependencyProperty.RegisterAttached("SelectedIndexChangedBehaviour",             typeof(SelectedChangedBehaviour), typeof(SelectedChanged), null);    
    }
}


Essentially this consists of a Dependency Property for the command and another one for the CommandParameter. The last part is to actually bind to it in XAML. First add the namespace to the xaml file

xmlns:xt="clr-namespace:PrismExtension.CommandBehaviours;assembly=PrismExtension"


Then in a control that is derived from ListBox this is the code I have used to bind the command to the control

<ListView Name="notesListView"
        xt:SelectedChanged.Command="{Binding SelectedNoteCommand}"
    xt:SelectedChanged.CommandParameter="{Binding ElementName=notesListView}">



On my viewmodel for the view I have a command called SelectedNoteCommand exposed as a read-only property which is the command that the control will fire on the selected item changing.

I pulled this together from a couple of sources – one is the click command itself from inside the Prism code. The second was a really informative video found here by Erik Mork of Silver Bay Labs. Also worth checking out if you are playing around with CommandBehaviours is nRoute because here you will find implementations of a whole swathe of CommandBehaviours! In fact check out nRoute anyway, as the guy writing it is a freaking Genius! The Office 2010 demo app is just beautiful.

PeteDoesStuff.NET .Net, Prism, WPF , ,

Project Structure For Prism Projects

June 22nd, 2009

This is how I am structuring my Prism projects.

ProjectName

This is the project which contains the shell and bootstrapper.

ProjectName.Infrastructure

This project contains all the classes that are shared between the modules such as events and common interfaces.

ProjectName.Infrastructure.Resources

In this project I put all my resources for the project such as styles and images.  This allows me to share specific icons and pictures etc between the different modules.

ProjectName.ModuleName

These projects are the modules loaded by the bootstrapper.  Inside the project I have a separate folder for Views and one for ViewModels.  The module class lives in the route of the assembly.  I currently am separating out each area of functionality into separate modules though there has been discussion as to whether you should have a Core Module which holds most or all the core functionality of the app.  I am against this as I think the notion of having more than 1 area of functionality in the one module does away with the advantages of modularity and increases the likelihood of having to do a full deployment when changing a single area of functionality.

PrismExtensions

This project contains my extensions for Prism or base code that helps speed up development.  So far it has a couple of RegionAdapters, the start of an MVVM framework and a custom bootstrapper that loads all the extensions automatically.

PeteDoesStuff.NET Prism, WPF ,

Prism Resources 2

June 18th, 2009

Videos

Silverbay Labs have done a couple of videos on Prism

  • Introduction to Composite Applications – this one covers all the basics of Prism.
  • Regions in Prism – this one shows a couple of interesting things that I haven’t seen much of elsewhere – RegionAdapters and RegionContext.  RegionAdapters allow you to use other controls to host regions than the ones that come with Prism. RegionContext allows you to share information between different views in the same region.

Training Courses and Presentations

Slides for my Prism-Tation by John McLoughlin from NxtGen Southampton. I went to see John’s Introduction to Prism talk at NxtGen Birmingham recently and can recommend seeing it if you get a chance.

General Articles on Prism

PeteDoesStuff.NET .Net, Prism, WPF

Onyx – Part 1

May 7th, 2009

After playing with Prism I have decided the next thing to look at is Onyx. This is a MVVM framework for WPF written by Bill Kempf. The best tutorial I have found on it so far is by Sacha Barber on CodeProject (WPF:FlipTile 3D) and these notes are based on my interpretation of his code.

The View-ViewModel interaction is setup declaratively in the XAML for the view as illustrated below:

<window title="TestWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
width="300"
height="300"
xmlns:local="clr-namespace:OnyxApp"
xmlns:onyx="http://schemas.onyx.com/2009/fx/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:class="OnyxApp.TestWindow"
onyx:view.model="{x:Type local:TestWindowViewModel}">

The TestWindowViewModel class here is coded as below

namespace OnyxApp
{
    public class TestWindowViewModel:ViewModel
    {
        public TestWindowViewModel(View view):
               base(view)
        {}

As far as I can see, this is the minimum amount of code to get the MVVM interaction going.

PeteDoesStuff.NET Onyx, WPF , ,

Prism Screencasts on Channel 9 Part 2

April 10th, 2009

Creating a modular application using Prism V2 – Screencast 3/4 : Implementing views and services

Step 5 – Creating the ViewModel

  • View model contains all the bindable elements that will appear in the view.
  • Use a ViewModel to allow easy testing and styling.
  • Just a normal class exposing data via properties.
  • Use constructor injection to add the ViewModel to the View and set the View’s DataContext to be the ViewModel.
  • Add HeaderData property to the ViewModel – if being used in tabs.
    Step 6 – Implementing Services

  • Create interface for service to allow testing in isolation/swapping of concrete types etc.
  • Add service interface to constructor for ViewModel using constructor injection.
  • Initialise data using the service interface.
  • Add the unity container to the constructor for the module class.
  • In the module initialisation code register the Service with the unity container using the following code
container.RegisterType<IServiceInterface, ServiceClass>();
  • If you want a singleton service use this instead
container.RegisterType<IServiceInterface, ServiceClass>(new ContainerControlledLifetimeManager);

Creating a modular application using Prism v2 – Screencast 4/4 : Decoupled Communication

This video covered the event aggregator and how to publish/subscribe to loosely coupled events.  Pretty much covered the same stuff as my post on event aggregation.

PeteDoesStuff.NET Prism, WPF ,

Prism Links

April 4th, 2009

I’ve been trying to collect together all the good resources I am finding on Prism.  Here is some of what I have found so far.

Downloads

General Blogs/Blog Postings on Prism

Articles

CodeProject Stuff

Articles are now starting to popup on Code Project about Prism – heres the first few I have found

Webcasts

PeteDoesStuff.NET Prism, WPF ,

Prism – Event Aggregation

April 2nd, 2009

These are my notes on how I got event aggregation working in Prism2.

Separate out the events that you want and any classes that they use into a separate assembly.  This assembly/project needs to reference Composite.Presentation.Desktop and Composite.Desktop.

The event types are derived from Microsoft.Practices.Composite.Presentation.Events.CompositePresentationEvent<TPayload>

Any project that is to publish or subscribe to those events needs a reference to the Assembly they are in.  Currently am favouring adding Infrastructure to the name of the assembly like the quick starts. 

To publish an Event

Raising class needs a reference to the EventAggregator passed into the constructor.

TypeOfEvent evnt = eventAggregator.GetEvent<TypeOfEvent>();
evnt.Publish(TPayload);

To subscribe to an Event

Subscribing class needs a reference to the EventAggregator passed into the constructor.

TypeOfEvent evnt = eventAggregator.GetEvent<TypeOfEvent>();
SubscriptionToken tkn = evnt.Subscribe(action);

Options for Subscribing

  • KeepSubscriberReferenceAlive – Subscribes with a strong reference which prevents the garbage collection of the subscriber.
    • Would need to unsubscribe manually.
    • Improves performance if publishing a large number of events in a short time.
  • ThreadOption – The following options are available for ThreadOption:
    • PublisherThread. Receives the event on the publisher’s thread.
    • BackgroundThread. Receives asynchronously on background worker thread.
    • UIThread. Recieves the event on the UI thread.
  • Filter – predicate.
    • Returns true if the payload of the event matches a criteria that the subscriber is interested in receiving.
    • Can be a lambda expression in WPF – has to be a separate method in SL2.

Unsubscribing from an Event

TypeOfEvent evnt = eventAggregator.GetEvent<TypeOfEvent>();
evnt.Unsubscribe(eventHandler);

evnt.Unsubscriber(subscriptionToken);

PeteDoesStuff.NET Prism, WPF

Prism Screencasts on Channel 9 Part 1

March 29th, 2009

There are 4 informative screencasts on Channel 9 on how to use Prism.  These are my notes on the first 2.

Creating a modular application using Prism V2 – Screencast 1/4 : Creating a shell and modules

Step 1 – Create a Shell Project.

Key things about the shell project :

  • This project contains the Unity Bootstrapper (assuming you are using Unity).  This is a class inherited from UnityBootstrapper and is required by Prism to create the shell etc.
  • Must override the CreateShell() method to return the shell for Prism to use.
  • Override the GetModuleCatalog() method to return the list of available modules.
  • To run the bootstrapper – create a new one in the application startup code and then run it.

Step 2 – Create  a Module Project.

Key things about the module project:

  • Module must expose IModule.
  • Fill in implementation of Initialize()
  • Ensure the module is added to the shell’s ModuleCatalog.
  • Catalog.AddModule(typeof(module));

Creating a modular application using Prism V2 – Screencast 2/4 : Visual Composition

Step 3 – Adding Regions to the Shell

  • Views in Prism sit within regions in the Shell.
  • These regions are managed by the RegionManager.
  • Add the namespace to the xaml file

xmlns:Regions=”clr-namespace:Microsoft.Practices.Composite.Presentation.Regions; assembly=Microsoft.Practices.Composite.Presentation”

  • Then add to the xaml for the content hosting control you want the region to sit in the following
Regions.RegionManager.RegionName=”name of region”

Step 4 – View Discovery

  • In the module project add a new user control to represent the view.
  • To the constructor of the module add IRegionManager.  This will automatically be resolved as Prism has previously registered the RegionManager with Unity.
  • To the initialise method add the following
this.regionManager.RegisterViewWithRegion(“regionName”, typeof(viewToInstantiate));

PeteDoesStuff.NET Prism, WPF , , ,

Learning Windows Presentation Foundation

March 14th, 2009

I recently decided to start looking at expanding my skills to include some of the new .NET 3.5 stuff. WPF looked the most interesting to start off with as its the new Windows Forms and also getting into the XAML and design side of .NET development looks like a good way to get my head around Silverlight. The learning curve so far hasn’t been nearly as steep as I was expecting – some of the things I was doing previously in Windows Forms now seem to be the MS-approved way of doing things now, such as the use of commands. I have found some really good free resources to help with picking up all the nuances

  • The Official Microsoft WPF and Windows Forms Site – This site has loads of code downloads and some really good training videos.  Most of the videos are pretty short and tell you how to do just one thing like how to use styles or perform layout.  So once you have a basic understanding these are pretty good, easily digestible snippets to add to your knowledge.
  • The WPF 08 Boot Camp – This site has the WPF boot camp course that was given by IdentityMine and various other people available to download for the grand price of free.  I am about half way through this so far and its pretty darn good.
  • Code Project – WPF Section – Lots of downloadable goodness here as well as some nice tutorials by Josh Smith (starting here) and Sacha Barber (starting here).

The next set of videos I am going to start watching is the WPF Soup to Nuts series.

    I also purchased a number of books – expect some reviews of them in the future.

PeteDoesStuff.NET .Net, WPF , ,