tags:

views:

100

answers:

2

Hi, thanks for taking a look at this question.

I have been building an application (VB/WPF) following Josh Smith's example of an MVVM pattern: Click here to view

My Views have Controls which trigger a Command upon an event, such as a button click and these are bound to properties in the ViewModel.

My ViewModel exposes properties of type ICommand which invoke the appropriate methods.

This has worked well, until now! I now want to use a Thumb Control to allow a user to move an object within a Canvas. I don't believe that the Thumb has a Command capability 'out of the box'. A Thumb raises a 'DragDelta' event when being moved. So my question is as follows:

How do I extend a Control's capability to issue a Command upon an event please?

I wish to issue a new Command, let's say 'onDragDelta' so that I can bind it to a property in my ViewModel just like my Buttons.

Thank you very much

A: 

Instead of using an ICommand, I would rather data bind the Thumb's current position to a property in your ViewModel. Now, if the position is changed, you could execute some method in your ViewModel with the difference as parameter.

I do not know whether this fits your needs, but that was my first thought.

gehho
A: 

What you want is to fire an ICommand in your ViewModel based on a FrameworkElement's RoutedEvent. Unfortunately, WPF doesn't support this "out-of-box". Some possibilities:

1) With Expression Blend 3 there is Microsoft.Expression.Interactivity.dll, which allows this. See WPF : Blend 3 Interactions / Behaviours for an example on how to do this.

2) You could have an event handler in your code-behind, which directly calls the appropriate ViewModel command. For example:

private void FrameworkElement_DragDelta(object sender, EventArgs e)
{
    this.MyViewModel.OnDragDelta(sender, e);
}

3) As part of the Cinch framework, there is an attached command behaviour. That way, you do not have to change your code-behind. For example:

Cinch:SingleEventCommand.RoutedEventName="DragDelta"
Cinch:SingleEventCommand.TheCommandToRun="{Binding Path=DragDeltaCommand}"

Note that this calls an ICommand and passes an object (actually an SCommandArgs) as command parameter. To get the actual routed event arguments in your command handler, do the following:

var sargs = args as SCommandArgs;
if (sargs == null)
{
    return;
}

var routedEventArgs = sargs.EventArgs as RoutedEventArgs; // Or whatever arguments you actually expect
if (routedEventArgs == null)
{
    return;
}

// Do something here with the event arguments

EDIT: Also take a look at http://stackoverflow.com/questions/939388/binding-commands-to-events

Daniel Rose
Thank you Daniel for your advice.I started by handling the Thumb's 'DragDelta' event in the code behind and bound the event's HorizontalChanged and VerticalChanged values to properties in my ViewModel. I then bound my Thumb's Canvas.Left and Canvas.Top properties to my ViewModel. Simple and neat but I felt the need to remove the code behind.I think that HorizontalChanged and VerticalChanged are only available as arguments of the Thumb's DragDelta event. With this in mind I'm not sure how I could bind these directly to the ViewModel.
Chris
If you only get the data as part of the event's arguments, then you'll either have to use the approach (1) or (3), or have a small code-behind. BTW I don't think there is anything wrong with having some code-behind, as long as there is no major (difficult to test) logic involved.
Daniel Rose