Sunday, January 16, 2011

GestureBehavior and GestureTrigger

The Silverlight toolkit has a GestureService and GestureListener that allows you to pick up events from gesture input. Oddly enough it doesn't include Xaml types to easily plug those into a page and bind those events to elements and MVVM commands.

Here is an example of using a simple behavior and set of triggers that allow you to do that.

<TextBlock Text="{Binding Welcome}">
    <i:Interaction.Behaviors>
        <li:GestureBehavior/>
    </i:Interaction.Behaviors>
    <i:Interaction.Triggers>
        <li:DoubleTapTrigger>
            <cmd:EventToCommand Command="{Binding DoubleTapCommand}" PassEventArgsToCommand="True"/>
        </li:DoubleTapTrigger>
    </i:Interaction.Triggers>
</TextBlock>
The TextBlock above is bound to a ViewModel that of course has a DoupleTapCommand. In this case a RelayCommand from MVVM Light:
public MainViewModel()
{
    DoubleTapCommand = new RelayCommand<GestureEventArgs>(e =>
    {
        MessageBox.Show("double tap " + e.OriginalSource.ToString());
    });

    DragStartedCommand = new RelayCommand<DragStartedGestureEventArgs>(Drag);
    DragDeltaCommand = new RelayCommand<DragDeltaGestureEventArgs>(Drag);
    DragCompletedCommand = new RelayCommand<DragCompletedGestureEventArgs>(Drag);
}

public RelayCommand<GestureEventArgs> DoubleTapCommand
{
    get;
    private set;
}

And we can implement a quick and dirty drag and drop:
Point _start;
private void Drag(DragStartedGestureEventArgs e)
{
    UIElement ui = e.OriginalSource as UIElement;
    if (ui != null)
    {
        if (!(ui.RenderTransform is TranslateTransform))
            ui.RenderTransform = new TranslateTransform();

        TranslateTransform t = ui.RenderTransform as TranslateTransform;

        _start = new Point();
        _start.X = t.X;
        _start.Y = t.Y;

        e.Handled = true;
    }
}

private void Drag(DragDeltaGestureEventArgs e)
{
    UIElement ui = e.OriginalSource as UIElement;
    if (ui != null)
    {
        TranslateTransform t = ui.RenderTransform as TranslateTransform;

        t.X += e.HorizontalChange;
        t.Y += e.VerticalChange;
        e.Handled = true;
    }
}

private void Drag(DragCompletedGestureEventArgs e)
{
    UIElement ui = e.OriginalSource as UIElement;
    if (ui != null && _start != null)
    {
        if (MessageBox.Show("Press cancel to abort this move.", "Really?", MessageBoxButton.OKCancel) == MessageBoxResult.Cancel)
        {
            TranslateTransform t = ui.RenderTransform as TranslateTransform;

            t.X = _start.X;
            t.Y = _start.Y;
            e.Handled = true;
        }
    }
}

public RelayCommand<DragStartedGestureEventArgs> DragStartedCommand
{
    get;
    private set;
}

public RelayCommand<DragDeltaGestureEventArgs> DragDeltaCommand
{
    get;
    private set;
}

public RelayCommand<DragCompletedGestureEventArgs> DragCompletedCommand
{
    get;
    private set;
}
Code and example is available here.

No comments:

Post a Comment