按住鼠标键时如何增加数字标签?

时间:2019-02-07 06:42:23

标签: c# wpf

C#反复调用函数以自动增加标签的值

这是WPF程序。它上面有一个标签(minuteTimerLabel),该标签显示两位数字,从00、01、02一直到99,以此类推。我希望该标签具有两个功能。首先,当鼠标左键在标签上(模拟点击)时,数字增加1。我已经能够实现这一点。但是我对第二个功能有疑问。

    private void MinuteTimerLabel_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        while(true)
        {
            if (timerMinute == 99)
            {
                return;
            }
            timerMinute += 1;
            minuteTimerLabel.Content = String.Format("{0:00}", timerMinute);
            Thread.Sleep(250);
        }
    }

在标签上按住鼠标左键几秒钟后,数字应自动保持一个一递增。 timerMinute是全局int变量。 使用我当前的代码,整个程序将锁定并且没有任何效果。当我删除while(true)时,按下鼠标时数字只会增加一次。如果我松开鼠标再按一次,它会起作用,但只能再次起作用。

4 个答案:

答案 0 :(得分:2)

为避免锁定UI,您需要使用某种形式的异步编码。我建议使用Microsoft的Reactive Framework。

获取“ System.Reactive.Windows.Threading”以获取这些位,并将using System.Reactive.Linq;添加到代码顶部。

然后您可以执行以下操作:

    private IDisposable _subscription = null;

    private void MinuteTimerLabel_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        _subscription =
            Observable
                .Interval(TimeSpan.FromMilliseconds(250.0))
                .Select(x => String.Format("{0:00}", x))
                .ObserveOnDispatcher()
                .Subscribe(x => MinuteTimerLabel.Content = x);
    }

    private void MinuteTimerLabel_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        _subscription.Dispose();
    }

它超级简单,干净。


private IDisposable _subscription = null;

private int _counter = 0;

private void MinuteTimerLabel_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    _subscription =
        Observable
            .Interval(TimeSpan.FromMilliseconds(250.0))
            .Select(x => String.Format("{0:00}", x))
            .ObserveOnDispatcher()
            .Subscribe(x => MinuteTimerLabel.Content = _counter++ % 100);
}

private void MinuteTimerLabel_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
    _subscription.Dispose();
}

答案 1 :(得分:0)

在这种情况下,您需要绑定两个事件,PreviewMouseDownPreviewMouseUp。然后计算出时间间隔,并以滴答/秒为单位降低标签的值。

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        PreviewMouseDown += Window3_PreviewMouseDown;
        PreviewMouseUp += Window3_PreviewMouseUp;
    }

    DateTime mouseDown;
    private void Window3_PreviewMouseDown(object sender, MouseButtonEventArgs e)
    {
        mouseDown = DateTime.Now;
    }

    private void Window3_PreviewMouseUp(object sender, MouseButtonEventArgs e)
    {
        var seconds = DateTime.Now.Subtract( mouseDown ).Seconds;

        //Condition code goes here..
        minuteTimerLabel.Content = seconds;
    }
}

答案 2 :(得分:0)

尝试以下代码:

代码将在另一个线程中运行,而不会阻塞Main Thread

private void MinuteTimerLabel_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    new Thread(Timer).Start();
}

private void Timer() {
    while(true)
    {
        if (timerMinute == 99)
        {
            return;
        }
        timerMinute += 1;
        minuteTimerLabel.Content = String.Format("{0:00}", timerMinute);
        Thread.Sleep(250);
    }
}

答案 3 :(得分:0)

非常适合CancellationToken异步等待模式

private CancellationTokenSource _cs;
private int _timerMinute =0;

private async void Label1_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
   _cs?.Cancel();
   _cs?.Dispose();
   _cs = new CancellationTokenSource();
   try
   {
      while (!_cs.Token.IsCancellationRequested)
      {
         await Task.Delay(200, _cs.Token);

         Label1.Content = $"{++_timerMinute:00}";
      }
   }
   catch (OperationCanceledException) {}
}

private void Label1_OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
   _cs?.Cancel();
   _cs?.Dispose();
}

如果您想变得棘手,则可以通过更改延迟来增加权重,例如,鼠标按下的次数越多