How to get the EventArgs as a CommandParameter using the AttachedCommandBehaviour
I have been asked many times how can I get the event args as a command parameter when using the AttachedCommandBehaviour.
Well the library does not support such a feature. I can do that yet I feel like the EventArgs should not flow down to the ViewModel because as such that is a UI thing… Yet in some case (such as for example if you want to set the Handled property to true of the Event args) this is needed.
I decided not to add this in the library yet I am gonna show how one can get this to work with some Attached Behavior.
The idea is to have a Attached Dependency property that handles the event and stores the last Event Args in another Attached Dependency Property. Here is the code to do so
1: public class MouseEventArgsHandler
2: {
3: #region LastMouseEventArgs
4:
5: /// <summary>
6: /// LastMouseEventArgs Attached Dependency Property
7: /// </summary>
8: public static readonly DependencyProperty LastMouseEventArgsProperty =
9: DependencyProperty.RegisterAttached("LastMouseEventArgs", typeof(MouseButtonEventArgs), typeof(MouseEventArgsHandler),
10: new FrameworkPropertyMetadata((MouseButtonEventArgs)null));
11:
12: /// <summary>
13: /// Gets the LastMouseEventArgs property. This dependency property
14: /// indicates ....
15: /// </summary>
16: public static MouseButtonEventArgs GetLastMouseEventArgs(DependencyObject d)
17: {
18: return (MouseButtonEventArgs)d.GetValue(LastMouseEventArgsProperty);
19: }
20:
21: /// <summary>
22: /// Sets the LastMouseEventArgs property. This dependency property
23: /// indicates ....
24: /// </summary>
25: public static void SetLastMouseEventArgs(DependencyObject d, MouseButtonEventArgs value)
26: {
27: d.SetValue(LastMouseEventArgsProperty, value);
28: }
29:
30: #endregion
31:
32: #region HandleMouseDoubleClick
33:
34: /// <summary>
35: /// HandleMouseDoubleClick Attached Dependency Property
36: /// </summary>
37: public static readonly DependencyProperty HandleMouseDoubleClickProperty =
38: DependencyProperty.RegisterAttached("HandleMouseDoubleClick", typeof(bool), typeof(MouseEventArgsHandler),
39: new FrameworkPropertyMetadata((bool)false,
40: new PropertyChangedCallback(OnHandleMouseDoubleClickChanged)));
41:
42: /// <summary>
43: /// Gets the HandleMouseDoubleClick property. This dependency property
44: /// indicates ....
45: /// </summary>
46: public static bool GetHandleMouseDoubleClick(DependencyObject d)
47: {
48: return (bool)d.GetValue(HandleMouseDoubleClickProperty);
49: }
50:
51: /// <summary>
52: /// Sets the HandleMouseDoubleClick property. This dependency property
53: /// indicates ....
54: /// </summary>
55: public static void SetHandleMouseDoubleClick(DependencyObject d, bool value)
56: {
57: d.SetValue(HandleMouseDoubleClickProperty, value);
58: }
59:
60: /// <summary>
61: /// Handles changes to the HandleMouseDoubleClick property.
62: /// </summary>
63: private static void OnHandleMouseDoubleClickChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
64: {
65: Control control = d as Control;
66: if (control != null)
67: {
68: if ((bool)e.NewValue)
69: control.MouseDoubleClick += ControlMouseDoubleClick;
70: else
71: control.MouseDoubleClick -= ControlMouseDoubleClick;
72: }
73: }
74:
75: static void ControlMouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
76: {
77: SetLastMouseEventArgs((DependencyObject)sender, e);
78: }
79:
80: #endregion
81: }
then you can use that value as the CommandParameter… Something like this
1: <ListBox ItemsSource="{Binding Data}"
2: local:MouseEventArgsHandler.HandleMouseDoubleClick="True"
3: acb:CommandBehavior.Event="MouseDoubleClick"
4: acb:CommandBehavior.Command="{Binding DoIt}"
5: acb:CommandBehavior.CommandParameter="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(local:MouseEventArgsHandler.LastMouseEventArgs)}" />
and here is what the command in the ViewModel looks like
1: DoIt = new SimpleCommand
2: {
3: ExecuteDelegate = x =>
4: {
5: //set the event as handled
6: ((MouseButtonEventArgs)x).Handled = true;
7: System.Diagnostics.Debug.WriteLine("Event handled");
8: }
9: };
The down side of this is that you have to do an attached property for every different event you want to handle, yet at the same time this should be a rare case and if it is not then you should really re think what you are doing with MVVM.
Hope it helps
I created a demo project for anyone that wants to have a look.
Animations and MVVM
This week I was asked from a colleague of mine, ‘How do I fire a command once a storyboard has completed?’. Do we have to break the MVVM here and write code behind. The answer is simple, HELL NO….
Attached Behavior to the rescue. Basically we can do this task by using an attached property, that will hook up to the Completed event of the storyboard and fire the command for us on the ViewModel. Here’s how to do this
1: var timeline = d as Timeline;
2: if (timeline != null && !timeline.IsFrozen)
3: {
4: timeline.Completed += delegate
5: {
6: ICommand command = GetCommand(d);
7: object param = GetCommandParameter(d);
8:
9: if(command != null && command.CanExecute( param ))
10: GetCommand(d).Execute(GetCommandParameter(d));
11: };
12: }
and here is how to use this in XAML
1: <EventTrigger RoutedEvent="ButtonBase.Click">
2: <BeginStoryboard>
3: <Storyboard cmds:CommandStoryboard.Command="{Binding Close}" >
4: <DoubleAnimation Storyboard.TargetName="border" Storyboard.TargetProperty="Height"
5: DecelerationRatio="1.0" Duration="0:0:0.5" To="0"/>
6: </Storyboard>
7: </BeginStoryboard>
8: </EventTrigger>
In the sample application (that is provided below with this article) shows how to animate some item in an items control and when the animation is completed the Storyboard executes a command that actually removes the item from the binding list.
I also created another simple class so that you can execute a Command from an EventTrigger. This is very handy since sometimes we want to execute a Command on a VM when some arbitrary RoutedEvent is raised. Here is the code for that
1: public class CommandTimeline : Storyboard
2: {
3: protected override Duration GetNaturalDurationCore(Clock clock)
4: {
5: return new Duration(TimeSpan.FromTicks(1));
6: }
7:
8: protected override Freezable CreateInstanceCore()
9: {
10: return new CommandTimeline();
11: }
12: }
and here is how to consume it
1: <EventTrigger RoutedEvent="FrameworkElement.Loaded">
2: <BeginStoryboard>
3: <cmds:CommandTimeline cmds:CommandStoryboard.Command="{Binding Test}" />
4: </BeginStoryboard>
5: </EventTrigger>
As you can see this reuses the attached behavior that is used on normal storyboards. The only difference between a Storyboard and a CommandTimeline is that a CommandTimeline returns a Duration of 0 so the Completed event gets raised immediately.
PLEASE NOTE: This can be only used in an event trigger. When this is used with DataTriggers etc you will get an exception saying that the Trigger cannot be sealed. This happens because you cannot hook up to the Completed event of a storyboard in a DataTrigger/Trigger. In order to workaround this I use AttacedRoutedEvents so that I can have EventTriggers executing my commands.
Sync Multi Select Listbox with ViewModel
Today one of my colleagues at Infusion asked me how he could sync up the selection of a ListBox with his ViewModel. WPF supports already single mode selection via the ICollectionView yet when it comes to MultiSelect there is no out of the box support in WPF.
Attached Properties to the rescue …..
I quickly when in my VS and wrote up a simple Attached property that hooks to the SelectionChanged event of the ListBox and populates a list of selected items to the ViewModel.
This is how the attached property looks like
1: #region SelectedItems
2:
3: /// <summary>
4: /// SelectedItems Attached Dependency Property
5: /// </summary>
6: public static readonly DependencyProperty SelectedItemsProperty =
7: DependencyProperty.RegisterAttached("SelectedItems", typeof(IList), typeof(ListBoxHelper),
8: new FrameworkPropertyMetadata((IList)null,
9: new PropertyChangedCallback(OnSelectedItemsChanged)));
10:
11: /// <summary>
12: /// Gets the SelectedItems property. This dependency property
13: /// indicates ....
14: /// </summary>
15: public static IList GetSelectedItems(DependencyObject d)
16: {
17: return (IList)d.GetValue(SelectedItemsProperty);
18: }
19:
20: /// <summary>
21: /// Sets the SelectedItems property. This dependency property
22: /// indicates ....
23: /// </summary>
24: public static void SetSelectedItems(DependencyObject d, IList value)
25: {
26: d.SetValue(SelectedItemsProperty, value);
27: }
28:
29: /// <summary>
30: /// Handles changes to the SelectedItems property.
31: /// </summary>
32: private static void OnSelectedItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
33: {
34: var listBox = (ListBox)d;
35: ReSetSelectedItems(listBox);
36: listBox.SelectionChanged += delegate
37: {
38: ReSetSelectedItems(listBox);
39: };
40: }
41:
42: #endregion
43:
44: private static void ReSetSelectedItems(ListBox listBox)
45: {
46: IList selectedItems = GetSelectedItems(listBox);
47: selectedItems.Clear();
48: if (listBox.SelectedItems != null)
49: {
50: foreach (var item in listBox.SelectedItems)
51: selectedItems.Add(item);
52: }
53: }
and here is how you would use it in the XAML
1: <ListBox ItemsSource="{Binding MyData}" Grid.Column="1" local:ListBoxHelper.SelectedItems="{Binding SelectedData}"
2: SelectionMode="Extended"/>
As you can see all you have to set is the List you want to populate in the ViewModel and the rest is taken care of by the Attached Property.
Please Note: This code was implemented quickly without any testing to prove an implementation idea, so please do review it before putting it in production
My first blog post on Windows Surface
I am excited with my first blog post for Infusion ( the company I am now working for).
The blog post is about Windows Surface and Manipulation processers. Some really cool stuff…
Have a look
http://www.infusion.com/surfaceblog/index.php/fun-with-surface-sdk-manipulationprocessor/
Mediator v2 for MVVM WPF and Silverlight applications
This last 2 weeks, us WPF Disciples have been talking a lot about the Mediator pattern for MVVM applications. Me and Josh Smith revised my previous Mediator implementation and found some problems with it.
Problem: There was a memory leak. Once a Mediator subscribes for one or more messages it would be kept in memory since the Mediator was holding a reference to the ViewModel.
Solution: We could have just exposed an unregister method so that when you call this method the Mediator would release the instance of the ViewModel. But sometimes it is hard to know when a ViewModel is going to die… So we went a step further and created the WeakAction. The WeakAction stores the instance of the ViewModel in a WeakRefence thus the ViewModel can be garbage collected without any problem and once it does get garbage collected the Mediator automatically removes that ViewModel registration from the list.
While we were at it we PIMPED the Mediator API
We added 2 approaches to subscribe to the Mediator and we also added support for (thanks to David Anson suggestion) strongly typed parameters.
So now the Mediator offers 2 methods of registration, a declarative way of registering and an imperative way as well.
The Declarative approach. (Supported in WPF and Silverlight)
This approach uses attributes so that you can decorate the messages that act as subscribers for messages.Here is an example
1: /// <summary>
2: /// Subscribe to Message1
3: /// </summary>
4: /// <param name="message">The message to be passed</param>
5: [MediatorMessageSink(MediatorMessages.Message1, ParameterType = typeof(SomeData))]
6: public void Test(SomeData data)
7: {
8: MessageBox.Show(data.Text + "\nReceived by: ColleagueA");
9: }
So you just have to decorate your method with MediatorMessageSink attribute and the Method will get invoked every time a message is broadcasted via the Mediator.
As you can see the Mediator also supports strongly typed parameters. In order to do so you have to specify the ParameterType property on the attribute as shown in the sample code above. You can pass 0 or 1 parameters. If you don’t have any parameters just ignore the ParameterType (since this is an named Property and you can just not set it )
When using the declarative approach you must register the instance of the ViewModel to the Mediator. This is just one line of code in the ViewModel constructor. Here is how you do that
1: public ColleagueA()
2: {
3: //Register all decorated methods to the Mediator
4: Mediator.Register(this);
5: }
This will inspect all methods of the ViewModel and look for the MediatorMessageSink attribute and register the appropriate methods to the Mediator. If you are going to have a base class for the ViewModels in your project and you can put this in the constructor of your base class. As simple an that.
The Imperative approach. (Supported in WPF ONLY)
If you do not want to use the attribute based registration we offer an imperative approach where you specify a method to be registered to a specific message. This implementation is exactly as it was in the old Mediator yet now it supports strongly typed parameters.
Here is how you can use this in your code
1: public ColleagueC()
2: {
3: //Register a specific delegate to the Mediator
4: Mediator.Register(MediatorMessages.Message1,
5: (Action<SomeData>)
6: delegate(SomeData x)
7: {
8: Test = x.Text;
9: MessageBox.Show(x.Text + " \nReceived by: ColleagueC");
10: });
11: }
This method is supported in WPF only since in Silverlight you cannot call an anonymous method (via reflection). If you try to use this method in Silverlight you will get an InvalidOperationException saying “This method is not supported in Silverlight”.
Conclusion
I packaged the Mediator in a class library so that you can go ahead and add a reference and reuse this library in your day to day projects.As always feedback is much appreciated.
[MVVM + Mediator + ACB = cool WPF App] – The MVVM
The Model View ViewModel is quite a hot subject right now in the WPF community. If you never read about MVVM I suggest that you read the following before you continue reading
- Introduction to Model/View/ViewModel pattern for building WPF apps by John Gossman (MVVM daddy)
- WPF & Silverlight Line of Business UI Design Pattern by Karl Shifflett
- WPF Apps With The Model-View-ViewModel Design Pattern by Josh Smith
MVVM in my sample app
Let me start by showing you a class diagram of the application structure
As you can see in the image above we have 3 layers. We have our Views, the ViewModels and the Models. (Please note that you can have n Tiers yet I am focusing just on 2 Tiers here, View and ViewModel….)
The View
The view is the “component” that renders the data on screen. This should be done all in XAML and not in C#. Why? Well UIs are much better built in a declarative fashion instead of an imperative one.
The View can be developed by a designer by using tools such as Blend and should not require any need from a developer. In the View the designer should express his artistic creativeness without any constrains from the developers.
Besides this when you put code in the View, this code is super hard to Unit test. From experiance I must say that 99% of the code written in the UI layer is never tested.
Ok so the designer sets the colors of the buttons etc… BUT!!!!
A - what about the data? From where can the designer get the data without having C# knowledge?
B – what about actions/events? How can a designer specify that when the button is clicked something should happen?
Well my friends that is the power of the WPF Databinding and the MVVM!
The ViewModel
The ViewModel is just a simple class (That has no coupling with the View and 100% unit testable). The ViewModel exposes data that the View can use to render the UI. Besides this the ViewModel also has Commands that the View can use to invoke actions. I will demo 2 pages that I created in the Sample App that explain how the ViewModel does this job.
A – what about the data?
To show you how the view renders data exposed by the ViewModel we will take the example in the screen shot above.
The ViewModel involved here is called ProjectListViewModel and the View is called ProjectList.xaml
The ViewModel exposes the data via a property called Projects. The property is shown below
1: ObservableCollection<WPFDisciples.Backend.ProjectDetails> projects
2: = new ObservableCollection<WPFDisciples.Backend.ProjectDetails>();
3: public ObservableCollection<WPFDisciples.Backend.ProjectDetails> Projects
4: {
5: get { return projects; }
6: }
As you can see this is simply a normal CLR property (not a DependencyProperty ). In this case the real magic is not in the property as such but in the type of Collection. Since the property exposes an ObservableCollection<T>, the databinding engine will listen to collection changed notifications and update the rendered data according.
This is how we bind to the data in the View’s XAML
1: <ListView ItemsSource="{Binding Projects}"
In this XAML we are doing List binding. We are specifying to the ListView that it should bind to the Projects property. The question is the Projects property of what object?
By default the source of a Binding is the DataContext of the element. In this case the DataContext will be the ViewModel. We specify that in the constructor of the View. There are many other nicer ways of doing this initialization of ViewModel in the View such as by using Onyx(this is a super cool WPF project!!!!! you must try it) or Dependency injection (such as in PRISM)
1: public ProjectList()
2: {
3: InitializeComponent();
4:
5: var viewModel = new ProjectListViewModel(Dispatcher);
6: DataContext = viewModel;
7: }
B – what about actions/events?
So let’s say you have a button and you want something to happen when the user clicks the button. Well the approach that we have been using in .Net is events. So a button would have a Click event and you would register an event handler for the event. Yet is this the right approach? Can a designer do this? Can you easily unit test such a method? Well I would say not really or better not easily…
A much better method has been introduced in WPF, the Commands. With commands you can delegate the work (such as a Click event) to the ViewModel. By doing so, the Designer can just specify what command to use for a button and viola he is done. Besides that the ViewModel can be unit tested much easier.
The example I picked from the sample app is the Save button to add a new Project. This can be found ProjectDetailsViewModel.cs
Here is the code that I used to expose the Command
/// <summary> /// Gets a Command to save the current project /// </summary> public SimpleCommand SaveProject { get; private set; }
Where SimpleCommand is a class that implements the ICommand interface. For more info on this visit this post.
and here is the code for the Command.
SaveProject = new SimpleCommand { ExecuteDelegate = Save, //Can execute only if there are no errors CanExecuteDelegate = x => String.IsNullOrEmpty(Project.Error) };
Conclusion
This article should have given you a basic idea of how the M V VM works… Next post will discuss how to overcome some of the problems with MVVM. I will show you how you have to start thinking in databinding so that you implement MVVM in a proper way.
bye bye Malta…. hello Infusion UK
From 20th April I will start working for Infusion Development, in London UK. This will be a hard move for me… I have my daughter here in Malta so I will still be coming back and forth in weekends. I know this sounds crazy but people do crazy things when they are in love… And I am in love with WPF so it all makes sense
I need to do more WPF and Infusion will for sure full fill this need. Being in UK will be cool since a lot of things happen in the UK WPF community. In fact I will be attending the WPF MVVM Training with Microsoft’s one and only Jamie Rodriguez and a special friend of mine Karl Shiflett! not to mention the crazy nights I am planning with one of my best friends Sacha Barber, the article machine
I am really looking forward for this!!!! So UK ready or not here I come
WPF Free Training tour
Yea believe it or not Microsoft’s Jaime Rodriguez and Karl Shifflett will be on tour giving WPF LOB training in several locations around the world. I will do my best to be in the London training myself as well, seeing Jaime and Karl teaching WPF is something that you don’t wanna miss for anything else
[MVVM + Mediator + ACB = cool WPF App] – Intro
Finally I managed to spare some time and build a WPF sample application to showcase the use of MVVM + Mediator and also how AttachedCommandBehaviours can be used to further reduce (or better eliminate) C# code in XAML code behind files. I am also using one of my favorite WPF libraries FluidKit. In the app I create my own 3D transition for the FluidKit TransitionPresenter (I will be posting a whole post on this).
I will be posting at least 4 posts
- MVVM
- MVVM and the Mediator pattern
- FluidKit CoverFlow and FluidKit TransitionPresenter
- Using AttachedCommandBehaviours
Here are some teaser screenshots of the application in action
Setup of application environment
This application uses a SQL Database so you will need an instance of SqlServer 2005 running (you can use SqlServer Express).
I packaged the database as a backup so all you need to do is restore the database from the SqlServer Management Studio Express (this is your easiest option). If you don’t have this I suggest you download it, it’s free.
To restore the database file (WPFDisciplesDB.bak) follow these steps
- First of all download the database file from here.
- Right click on the Databases folder in the SQL Server Management Studio Express and select Restore database
This will open a dialog for you. In the Restore Database dialog enter a name for the database in the “To database” text field > Select “From device” radio button and browse for the WPFDisciples.bak that you downloaded. The file will appear in the list. Tick the checkbox (which is un checked by default) and press ok.
Now that we have our database set up all we need to do is specify in the app.config the connection string of the new database and we are done.
Stayed tuned because this should be real fun
aaaa I nearly forgot… The data in the database is not the full version… I will add more projects from the mighty WPF Disciples as time goes by…. Will continue updating the download link here (and put a comment or something to show you that I updated the db version)
Download Full Source Code from HERE
Just in case you missed it, here is a copy of the database




