2011-04-19 69 views
2

我的WinForms程序中有一個跟蹤欄,它通過移動一個巨大且耗時的方法將被刷新。看看下面的代碼:如何檢查TrackBar滑動鼠標按住並釋放

trackBar_ValueChanged(object sender, EventArgs e) 
{ 
    this.RefreshData(); 
} 

這條賽道酒吧有20個步驟。如果用戶在我的情況下抓住軌跡條的滑塊並將其從20拉到0,則'RefreshData'將被執行20次,儘管它在結束'RefreshData'的值爲0的過程時顯示正確的數據,我想要做類似當trackBar滑塊已經釋放時它只調用'RefreshData',所以它不會處理所有步驟到軌跡條上的釋放點。

任何幫助和提示,以實現這一點將是appericiated! 謝謝。

+1

mmmm,WPF? Silverlight的?的WinForms? (等) – 2011-04-19 14:30:04

+0

它在WinForms – 2011-04-19 14:48:36

+0

謝謝你,現在你會得到更好的答案:) – 2011-04-19 14:51:29

回答

1

,我已經做了這樣的事情之前是使用計時器的方式。每當TrackBar的值發生變化時,重置定時器以使其在500ms內(或任何適合您的情況)觸發。如果用戶在定時器觸發前更改了該值,它將再次被重置,這意味着即使它多次更改,定時器也只會觸發一次。

這裏唯一需要注意的是計時器會觸發另一個線程,並且您將無法從該線程更新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窗體計時器來執行計時。這裏的區別在於,在計算運行時您將鎖定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(); 
    } 
} 
+0

@Mike謝謝我會嘗試這個,但我正在尋找更簡單的事情,也許只是事實上。 – 2011-04-19 20:50:07

+0

不幸的是,我不認爲你會在這裏找到適合你的目的的事件 - 基本上你想要一個名爲「UserFinishedUpdating」的事件,當他們停止改變價值時觸發它,無論他們是否在做鼠標或鍵盤。最終,這是這段代碼會給你的。讓我知道你如何繼續下去,如果你需要解釋任何部分。 – 2011-04-19 22:04:57

+0

爲定時器啓動一個新線程有什麼好處?爲什麼你不能在UI線程上運行定時器(使用'System.Windows.Forms.Timer'),並且只有在用戶完成將滑塊移動了預定的毫秒數時才調用update方法? – 2011-04-20 03:27:54

4

如何:

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

考慮一個新的線程執行長時間運行的方法。在重新啓動它之前,維護對該線程的引用並調用Thread.Abort()。