WPF按钮样式-触摸和IsMouseOver

4
我正在编写一个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 并不是解决这个问题的方法。

<Setter Property="Stylus.IsPressAndHoldEnabled" Value="False"/>

有什么建议吗?

1个回答

1
我建议您考虑添加一个DataTrigger属性,以便检测用户是否使用触摸设备。例如this simple boolthis。然后,您可以应用MultiDataTrigger,仅在非触摸设备(即鼠标驱动)上显示高亮。以下是一个小的可复现示例。

MainWindow.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>

MainWindow.xaml.cs

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;
    }
}

比直接丢失鼠标更好。但仍不是最佳选择。这需要在子类控件或父级中定义一个TouchEnabled属性。 - Eddie Wyatt
这并不是一个同时支持触摸和鼠标的设备的解决方案。在2020年底之前,这样的设备已经存在。 - Delbert

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接