【问题标题】:Event for when a Button is held clicked for some time当一个按钮被点击一段时间的事件
【发布时间】:2014-12-28 05:58:46
【问题描述】:

我正在用 WPF 和 MVVM 模拟手持设备(viewmodel 是一个状态机,view 是一个带按钮的模拟塑料外壳)。

打开和关闭设备的手势是“长按”按钮。例如,在使用过程中,如果我按下“确定”按钮,它会显示一些屏幕,但如果我按住它点击超过三秒钟,它应该(以模拟方式)关闭设备。

我查看了RepeatButton 及其DelayInterval 属性,但它们似乎触发了相同的Click 事件。如果我按住按钮不到三秒钟,我需要触发一个普通的Click,如果我按住按钮超过三秒钟,则触发 另一个,不同的LongClick(可能一次) .

我怎样才能做到这一点,使用 RepeatButton 甚至是常规 Button?

【问题讨论】:

    标签: wpf button click repeatbutton


    【解决方案1】:

    您可以这样做的一种方法是绑定到 MouseDown 和 MouseUp 事件。使用在 MouseDown 上启动的秒表之类的东西,并检查在 MouseUp 上经过的时间量。如果少于 3 秒,请执行 Click() 操作。如果超过 3 秒,请执行 LongClick() 操作。

    private void Button_PreviewMouseDown(object sender, MouseButtonEventArgs e)
    {
        stopwatch = new Stopwatch();
        stopwatch.Start();
    }
    
    private void Button_PreviewMouseUp(object sender, MouseButtonEventArgs e)
    {
        stopwatch.Stop();
    
        if (stopwatch.ElapsedMilliseconds >= 3000)
        {
             // do Click()
        }
        else
        {
            // do LongClick
        }
    }
    

    这是一个重复按钮的解决方案:

    private bool isLongClick;
    private bool hasAlreadyLongClicked;
    private void RepeatButton_PreviewMouseDown(object sender, MouseButtonEventArgs e)
    {
        isLongClick = false;
        hasAlreadyLongClicked = false;
        stopwatch = new Stopwatch();
        stopwatch.Start();
    }
    
    private void RepeatButton_Click(object sender, RoutedEventArgs e)
    {
        if (!hasAlreadyLongClicked && stopwatch.ElapsedMilliseconds >= 3000)
        {
            hasAlreadyLongClicked = true;
            isLongClick = true;
            // do your LongClick action
        }
    }
    
    private void RepeatButton_PreviewMouseUp(object sender, MouseButtonEventArgs e)
    {
        if (!isLongClick)
        {
            // do short click action
        }
    }
    

    这里的诀窍是,RepeatButton 基本上只是一个在每个间隔触发 Click 的 Button。因此,如果我们在 PreviewMouseDown 上为按钮启动秒表,我们可以在每次触发 Click 事件时检查秒表上的经过时间,并根据结果修改我们的操作。

    【讨论】:

    • LongClick 事件不应该等到我松开鼠标,而是等到三秒钟后。但这将是一个有趣(且简单且有效)的解决方案。会试一试的。
    • @heltonbiker 嗯。这比按钮更接近RepeatButton的功能。我会看看我能不能想出类似的东西。
    • 是的,我当前的小部件是重复按钮,因为这是它们模拟的硬件行为。我的问题的核心是“如何区分第一次点击和后续点击?”
    • @heltonbiker 知道了!查看第二个解决方案。
    • 您的最后一个代码让我相信,在开始获取 LongClick 事件之前,我总是会获得可变数量的 Click 事件?
    【解决方案2】:

    经过一个周末的冥想,我设计了以下可行的解决方案:

    1. 在 ViewModel 中创建两个布尔标志:ClickedShortClickedLong
    2. 通过命令将按钮上的Command 属性绑定到ViewModel 上的OK 方法;
    3. OK命令是这样的:

      public void OK()
      {
          if (!ClickedShort)
          {
              HandleShortClick();
              ClickedShort = true;
          }
          else if (!ClickedLong)
          {
              HandleLongClick();
              ClickedLong = true;
          }
      }    
      
    4. 在 XAML 中有两个 CheckBox,IsChecked 属性绑定到布尔标志。这些只是中继,因此我可以通过绑定将信息从 View 发送到 ViewModel:

          <CheckBox x:Name="ClickedShort" IsChecked="{Binding ClickedShort, Mode=OneWayToSource}" Visibility="Collapsed"/>
          <CheckBox x:Name="ClickedLong" IsChecked="{Binding ClickedLong, Mode=OneWayToSource}" Visibility="Collapsed"/>
      
    5. 在我释放按钮时,在 OK 按钮中有一个 MouseUp 事件以将这些标志重置为 false。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多