WPF按钮样式-触摸式和IsMouseOver

WPF按钮样式-触摸式和IsMouseOver,wpf,Wpf,我正在写一个WPF主题,将在触摸设备上使用。我还希望这个主题在使用鼠标的设备上提供正常的行为 我遇到的问题是,“IsMouseOver”的触发器被触发,并且在触摸控件时保持打开状态。我的研究表明,这是一个已知的问题,因为当触摸控件时,IsMouseOver会设置为true,但不会取消设置。我看到的解决这个问题的方法是从样式中删除“IsMouseOver”触发器。我对这种方法不感兴趣,因为移除IsMouseOver触发器会丢失鼠标悬停的视觉提示 <ControlTemplate.Trigge

我正在写一个WPF主题,将在触摸设备上使用。我还希望这个主题在使用鼠标的设备上提供正常的行为

我遇到的问题是,“IsMouseOver”的触发器被触发,并且在触摸控件时保持打开状态。我的研究表明,这是一个已知的问题,因为当触摸控件时,IsMouseOver会设置为true,但不会取消设置。我看到的解决这个问题的方法是从样式中删除“IsMouseOver”触发器。我对这种方法不感兴趣,因为移除IsMouseOver触发器会丢失鼠标悬停的视觉提示

<ControlTemplate.Triggers>
    <Trigger Property="IsMouseOver" Value="true">
        <Setter Property="Background" TargetName="border" Value="{StaticResource Button.MouseOver.Background}"/>
        <Setter Property="BorderBrush" TargetName="border" Value="{StaticResource MouseOver.Border}"/>
     </Trigger>
</ControlTemplate.Triggers>

此外,将“Stylus.IsPressAndHoldEnabled”设置为false也不是此问题的解决方案


建议?

我建议您考虑添加一个能够检测用户是否在触摸设备上的DataTrigger属性。类似于或

然后,您可以应用MultiDataTrigger,仅当它们位于非触控设备(即鼠标驱动)上时才显示高亮显示。这是一个可复制的小样本

main window.xaml

<Grid>
    <StackPanel>
        <TextBlock Text="{Binding TouchStatus}" Margin="5" HorizontalAlignment="Center"/>
        <Button Margin="5" Content="Push" HorizontalAlignment="Center" Padding="5,15" BorderThickness="3">
            <Button.Style>
                <Style TargetType="Button">
                    <Setter Property="BorderBrush" Value="Blue"/>
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="Button">
                                <Border x:Name="border" 
                                        BorderBrush="{TemplateBinding BorderBrush}" 
                                        BorderThickness="{TemplateBinding BorderThickness}" 
                                        Background="{TemplateBinding Background}" 
                                        Padding="{TemplateBinding Padding}" 
                                        HorizontalAlignment="{TemplateBinding HorizontalAlignment}">
                                    <ContentPresenter/>
                                </Border>
                                <ControlTemplate.Triggers>
                                    <MultiDataTrigger>
                                        <MultiDataTrigger.Conditions>
                                            <Condition Binding="{Binding RelativeSource={RelativeSource Mode=Self},Path=IsMouseOver}" Value="True"/>
                                            <Condition Binding="{Binding TouchEnabled}" Value="False"/>
                                        </MultiDataTrigger.Conditions>
                                        <Setter Property="BorderBrush" TargetName="border" Value="Yellow"/>
                                    </MultiDataTrigger>
                                </ControlTemplate.Triggers>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </Button.Style>
        </Button>
    </StackPanel>
</Grid>

总比彻底松开鼠标要好。仍然不是最优的。这需要在子类控件或父控件中定义TouchEnabled属性。
public partial class MainWindow : Window, INotifyPropertyChanged
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = this;
        UpdateTouchStatus();
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    private string touchStatus;
    private bool touchEnabled;
    public string TouchStatus { get => this.touchStatus; set { this.touchStatus = value; OnPropertyChanged(); } }
    public bool TouchEnabled { get => this.touchEnabled; set { this.touchEnabled = value; OnPropertyChanged(); } }

    private void UpdateTouchStatus()
    {
        if (!HasTouchInput())
        {
            this.TouchEnabled = true;
            this.TouchStatus = "This is a touch enabled device";
        }
        else
        {
            this.TouchEnabled = false;
            this.TouchStatus = "This is NOT a touch enabled device";
        }
    }

    public bool HasTouchInput()
    {
        foreach (TabletDevice tabletDevice in Tablet.TabletDevices)
        {
            //Only detect if it is a touch Screen not how many touches (i.e. Single touch or Multi-touch)
            if (tabletDevice.Type == TabletDeviceType.Touch)
                return true;
        }

        return false;
    }
}