8

I am working on a WPF application which is being used on a Touch Screen Tablet. I develop using VS2015 IDE and I use my Mouse to debug.

I must handle buttons' down and up events to execute certain tasks. I use PreviewMouse and PreviewTouch event handlers and I have a problem in every case I use:

  • Case 1: Using PreviewMouseDown,PreviewMouseUp,PreviewTouchDown and PreviewTouchUp. For each button, I need to duplicate my code to include separate Touch and Mouse Event handlers but the exact same functionality. I do this for me to be able to use the Application (Mouse) and for the the user to use it (Touch). Problem: Touch Event Handlers executes Mouse Event Handlers; Causing the application to duplicate the behavior. Ex: A button that increments x by one, will increment by one if you "Click" it but increment by two if you "Touch" it.

  • Case 2: Using Click, PreviewMouseUp and PreviewTouchUp. Problem: The PreviewTouchUp and PreviewMouseUp do not get called on Mouse Click.

  • Case 3: Create a method for each button and call it from both Touch and Mouse events like How to get Touchscreen to use Mouse Events. Problem: Duplicate behavior (method gets called twice)

  • Case 4: Remove all Touch events since PreviewMouseDown and PreviewMouseUp are being executed on any Touch. The behavior works but I need to Touch certain positions on the button in order for it to execute. (Transparency? I must touch exactly one position - like a mouse?)

  • Case 5: Using MouseUp and MouseDown instead of Preview. Didn't work on Touch at all, touching any position on the button.

I want something similar to this Prevent a WPF application to interpret touch events as mouse events but only on the tablet. I still need to use my mouse in my environment. How can I fix that?

Button sample XAML:

<Button x:Name="locationScrollUpButton" Margin="0,5,5,0" Background="Transparent" Padding="0" Grid.Row="1" Grid.Column="1" PreviewMouseUp="locationScrollUpButton_PreviewMouseUp" PreviewMouseDown="locationScrollUpButton_PreviewMouseDown" BorderThickness="0" PreviewTouchDown="locationScrollUpButton_PreviewTouchDown" PreviewTouchUp="locationScrollUpButton_PreviewTouchUp" >
    <StackPanel>
        <TextBlock x:Name="locationUpButtonText" Text="Up" FontSize="13" Margin="0,2,0,4" HorizontalAlignment="Center" VerticalAlignment="Center"/>
        <Image x:Name="locationUpButtonImage" Source="/ProjectName;component/Resources/CaptureView/Location-Scroll-Up-White.png" Width="55" Height="60"/>
    </StackPanel>
</Button>
Community
  • 1
  • 1
Khalil Khalaf
  • 9,259
  • 11
  • 62
  • 104
  • try using this condition as a guard see if it works. `Mouse.LeftButton == MouseButtonState.Pressed` – M.kazem Akhgary May 17 '16 at 18:19
  • @M.kaz I see ! I think I got what you mean. Xaml should look like this: `... PreviewMouseUp="Button_PreviewMouseUp" PreviewTouchUp="Button_PreviewMouseUp"...` but different events no? **Edit:** Use that condition where? (or what do you mean by guard) – Khalil Khalaf May 17 '16 at 18:19
  • 2
    dirty way.....using a debugger see which one get executed first. if touch event called first set a boolean value to `true`. for example `touch = true` then use a guard for next mouse event. `if(!touch) /* do things */ else touch = false;`. in this way you always suspend mouse events after touch events. if mouse events gets executed first use the same logic. – M.kazem Akhgary May 17 '16 at 18:34
  • @M.Kaz I have an idea ! why not get rid of the whole Touch events? since Mouse's are being called on Touch right? But.. let's say the button should change a variable from `x` to `y` on click and back to `x` on release. The behavior doesn't happen on _every_ touch. it only happens almost 1/3 of the times. Do you have any idea why?? Is it like, the mouse event is looking for a single position but I am touching several positions with my finger, so it doesn't execute unless I touch exactly one position? or something like that? – Khalil Khalaf May 17 '16 at 18:40
  • @M.ka I can't use a debugger on the touch tablet for now or the soon future :( – Khalil Khalaf May 17 '16 at 18:43
  • can you show xaml part. not whole code but the part that you define events. – M.kazem Akhgary May 17 '16 at 18:45
  • @M.Kaz I added it and also mentioned that I am using `PreviewMouse` events and not the normal ones. – Khalil Khalaf May 17 '16 at 18:47
  • 1
    @M I ended up with the dirty way :D See answer – Khalil Khalaf May 18 '16 at 14:27

2 Answers2

10

Check the StylusDevice property of the MouseEventArgs. If it is null, then the mouse event is not a promoted touch event. If it's not null, then the StylusDevice will be the touch device that initiated the touch that got promoted.

Rob LaDuca
  • 191
  • 2
4

So I ended up doing it using a cool hack. Based on Ahmad's answer on this other question HERE we know the fire order of the handlers:

On Touch Devices:

TouchDown > PreviewMouseDown > TouchUp > PreviewMouseUp

On Non Touch:

PreviewMouseDown > PreviewMouseUp

And based on @M.Kazem comments here. The fix now looks something like this:

private bool ButtonPreview = true;
private void Button_TouchDown(object sender, TouchEventArgs e)
{
    // task 1
    ButtonPreview = false;
}
private void Button_TouchUp(object sender, TouchEventArgs e)
{
    // task 2
    // ..
}
private void Button_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
    if (ButtonXPreview)
    {
        // task 1
    }
    else
        ButtonXPreview = true;

}
private void Button_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{
    if (ButtonXPreview)
    {
        // task 2
    }
    else
        ButtonXPreview = true;
}
Khalil Khalaf
  • 9,259
  • 11
  • 62
  • 104