C# 如何在按住和松开鼠标的情况下检查轨迹栏是否滑动

C# 如何在按住和松开鼠标的情况下检查轨迹栏是否滑动,c#,winforms,mouseevent,mouse,trackbar,C#,Winforms,Mouseevent,Mouse,Trackbar,我的WinForms程序中有一个轨迹栏,通过移动它,将刷新一个巨大且耗时的方法。请查看以下代码: trackBar_ValueChanged(object sender, EventArgs e) { this.RefreshData(); } 这个轨迹栏有20个台阶。在我的例子中,如果用户抓取轨迹栏的滑块并将其从20拉到0,“RefreshData”将执行20次,尽管它在结束值为0的“RefreshData”过程时显示正确的数据,我想做一些事情,比如当轨迹栏滑块被释放时,它只调用“

我的WinForms程序中有一个轨迹栏,通过移动它,将刷新一个巨大且耗时的方法。请查看以下代码:

trackBar_ValueChanged(object sender, EventArgs e)
{
     this.RefreshData();
}
这个轨迹栏有20个台阶。在我的例子中,如果用户抓取轨迹栏的滑块并将其从20拉到0,“RefreshData”将执行20次,尽管它在结束值为0的“RefreshData”过程时显示正确的数据,我想做一些事情,比如当轨迹栏滑块被释放时,它只调用“RefreshData”,这样它就不会处理到轨迹栏上释放点的所有步骤

任何帮助和提示,以实现这一点将是胃口!
谢谢。

试试
KeyUp
事件:


我以前做这类事情的方法是使用计时器。每次轨迹栏的值改变时,重置计时器,使其在500毫秒内触发(或任何适合您的时间)。如果用户在计时器触发之前更改了该值,它将再次重置,这意味着即使它更改多次,计时器也只触发一次

这里唯一需要注意的是计时器将在不同的线程上启动,并且您将无法从该线程更新UI,因此您必须重新调用UI线程以在那里进行更改。不过,也就是说,如果你能将大部分昂贵的工作转移到这个后台线程上,你就能让UI保持更长的响应时间

这里有一些示例代码,可以让您了解我的意思

public partial class Form1 : Form
{
    private int updateCount;
    private System.Threading.Timer timer;

    public Form1()
    {
        this.InitializeComponent();
        this.timer = new System.Threading.Timer(this.UpdateValue);
    }

    private void UpdateValue(object state)
    {
        // Prevent the user from changing the value while we're doing
        // our expensive operation
        this.Invoke(new MethodInvoker(() => this.trackBar1.Enabled = false));

        // Do the expensive updates - this is still on a background thread
        this.updateCount++;

        this.Invoke(new MethodInvoker(this.UpdateUI));
    }

    private void UpdateUI()
    {
        this.label1.Text = this.updateCount.ToString();

        // Re-enable the track bar again
        this.trackBar1.Enabled = true;
    }

    private void trackBar1_ValueChanged(object sender, EventArgs e)
    {
        this.timer.Change(TimeSpan.FromMilliseconds(500), new TimeSpan(-1));
    }
}
编辑:这里有一个解决方案,它使用win forms计时器进行计时。这里的区别是,在计算运行时,您将锁定UI;在你的情况下,这可能是好的,也可能不是好的

public partial class Form1 : Form
{
    private int updateCount;
    private Timer timer;

    public Form1()
    {
        this.InitializeComponent();

        this.timer = new Timer();
        this.timer.Interval = 500;
        this.timer.Tick += this.Timer_Tick;
    }

    private void Timer_Tick(object sender, EventArgs e)
    {
        this.timer.Stop();

        this.updateCount++;
        this.label1.Text = this.updateCount.ToString();
    }

    private void trackBar1_ValueChanged(object sender, EventArgs e)
    {
        this.timer.Stop();
        this.timer.Start();
    }
}
那么:

Boolean user_done_updating = false;

private void MytrackBar_ValueChanged(object sender, EventArgs e)
{
    user_done_updating = true;
}

private void MytrackBar_MouseUp(object sender, MouseEventArgs e)
{
    if (user_done_updating)
    {
        user_done_updating = false;
        //Do Stuff
    }
}

考虑在新线程中执行长时间运行的方法。维护对该线程的引用,并在重新启动之前调用thread.Abort()。

mmmm,WPF?银灯?Winforms?(等)谢谢,现在你会得到更好的答案:)鼠标的问题是,当用户用键盘更改轨迹栏的值时,它不会被触发。在这种情况下,您仍然需要处理
ValueChanged
。@迈克,谢谢,我会尝试这个,但我一直在寻找更简单的方法,可能只是针对事件。不幸的是,我认为您在这里找不到适合您的目的的事件-实际上您想要的是一个名为“UserFinishedUpdating”的事件当他们停止更改值时,无论是使用鼠标还是键盘,都会触发该命令。最终,这就是这段代码将提供给您的内容。让我知道你进展如何,如果你需要任何部分解释。为计时器旋转一个新线程有什么好处?为什么你不能在UI线程上运行计时器(使用
System.Windows.Forms.timer
),并且只在用户完成滑块移动预定毫秒数时调用update方法?我想这里唯一的好处是你可以在后台线程上运行任何昂贵的计算,但你是对的,如果您不介意锁定UI,您可以使用窗体计时器-我也用该选项更新了答案,谢谢。@Mike再次感谢。我希望UserDoneUpdating是可用的:P您的代码运行良好!