Wpf: Click event is rarely raised when using touch

Created on 20 Dec 2018  路  14Comments  路  Source: dotnet/wpf

  • .NET Core Version:
    3.0.100-preview-009812
  • Windows version:
    Version 1803
  • Does the bug reproduce also in WPF for .NET Framework 4.8?:
    Yes

    Problem description:
    Click event is rarely raised when using touch in new windows.

    Actual behavior:
    Touching (clicking) the button does nothing the first 10 times. 11th time the click event is raised.

    Expected behavior:
    Click event on button should be raised on first touch.

    Minimal repro:
    Touch.zip
    MainWindow.xaml:

<Window 
    x:Class="Touch.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="400" Width="400">
    <StackPanel>
        <TextBox Text="{Binding Integer}" FontSize="48" />
        <TextBox Text="{Binding Integer}" FontSize="48" />
    </StackPanel>
</Window>

MainWindow.xaml.cs:

public partial class MainWindow
{
    public MainWindow()
    {
        InitializeComponent();

        DataContext = new ViewModel();
    }
}

ViewModel.cs:

public class ViewModel
{
    private int _integer;

    public int Integer
    {
        get => _integer;
        set
        {
            _integer = value;
            new DialogWindow().ShowDialog();
        }
    }
}

DialogWindow.xaml:

<Window
    x:Class="Touch.DialogWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="200" Width="200">
    <Grid>
        <Button Content="Close" Click="OnClick" />
    </Grid>
</Window>

DialogWindow.xaml.cs:

public partial class DialogWindow
{
    public DialogWindow()
    {
        InitializeComponent();
    }

    private void OnClick(object sender, RoutedEventArgs e)
    {
        Close();
    }
}

When one of the textboxes has content changed, and you uses touch to focus the other textbox, the DialogWindow will pop up. Now the problem occurs, and we have to press (touch) the close button multiple times (etc. 11 times on one of our devices) before the click event happens and the dialog closes.

TouchDown event works properly. We're also experincing this on other elements than Button, for example TextBox. It is therefore not a solution to switch to TouchDown event. Everyhing in the new window seems to be buggy.

Related links:
https://stackoverflow.com/questions/53851382/wpf-click-event-is-not-raised-on-touch-screen
https://stackoverflow.com/questions/28441538/touching-a-wpf-button-does-sometimes-not-invoke-the-click-handler-under-windows

issue-type-bug

Most helpful comment

@stevenbrix Touch is not first class in WPF as it is in UWP. If touch doesn't promote to mouse (and therefore click) the button will not click.

All 14 comments

@Jogge can you elaborate on why using touch events is not a solution?

@stevenbrix Touch is not first class in WPF as it is in UWP. If touch doesn't promote to mouse (and therefore click) the button will not click.

I've got the same problem.
In your project you can change clickEvent by Mousedown or PreviewMouseDown. On TouchScreen you will have the same problem if you use your finger. With mouse it works well.
Any news or workaround ?

@StefGuichard unfortunately we have not found any workarounds, other than using the TouchDown event... 馃槦

I seems to be related to that issue 450. At the moment you click the close button in dialog and it doesn't work you can see that it has 0 TouchesOver on MainWindow but 2 TouchesOver on DialogWindow. This is not correct as I only ever touched the screen with 1 finger at a time.

I don't know exactly how .NET handles touch internally but I feel the same part of WPF code is responsible for both cases.

I have had this issue with numerous projects over the last four years. I have been able to correct the issue by switching from a multi-touch driver to a single-touch driver on our touch screens. Unfortunately, I have not been able to find a single touch driver for Windows 10 that works yet. I may have to downgrade my latest project to Windows 7.

Hello are there any workarounds or fixes of this bug available?

This is still a huge issue, ShowDialog doesn't work well with multi-touch displays.

It does respond if I tap the Window 8-10 times then it becomes responsive. I have tried all of the focus options, almost every setting and nothing makes a difference, I have had to make my own showDialog functionality, but it needs to be shown with ShowDialog ideally.

@hunterzzzpro can you share how you do this? In our main app we have an abstraction around ShowDialog anyway so this kind of workaround might work better than other things we tried (which all introduced their own bugs).

I use WPF on Beckhoff touch screens and was able to get my project to work with the eGalaxTouch_5.14.0.17601 driver in single touch mode.

@Stannieman My requirements were to have the window pop up and not allow the user to click outside of that window.

So I did the following:
Used .Show()
set the window.Topmost = true;
then made an event for the MainWindow to subscribe too that makes a hidden rectangle visible, but it's transparent. This stops any of the buttons from being clicked/pressed.

Very hacky which is why I need ShowDialog() fixed. Probably won't help in your case, but it's a temp fix for me (Tight deadlines!)

@hunterzzzpro yeah approach with overlay is actually ok for us, but Show() not blocking until dialog is closed is kind of a problem.

Actually now that I think about it, probably the fact that Show() (and thus really the main window's message loop) does not wait for the dialog to close is exactly why it works for you.

Slightly offtopic, but here is how we are doing modal loops without ShowDialog in WinForms. It's how PropertyGrid shows its dropdown popups. No idea if it helps with this particular problem.

This issue happens when Button elements are located in a user control or window along side a text box or could be with other elements.

You need to assign a touch down event along side assigning a command parameter and a command on the button element.

If the touch down event is fired, manually fire the command. Example below

            MapEntity commandParameter = (MapEntity)(((Button)sender).CommandParameter);

            var viewModel = (FindADISViewModel)DataContext;
            if (viewModel.OpenDIS.CanExecute(commandParameter))
                viewModel.OpenDIS.Execute(commandParameter);
Was this page helpful?
0 / 5 - 0 ratings