2012-01-25 26 views
4

我有一個相當複雜的形式,它提供了一個運行腳本(我們自己的類型)的選項。在運行時,我不想完全鎖定UI,因此我想在一個線程中啓動它。目前爲止這麼好,但爲了防止用戶搞亂我需要有選擇地禁用部分UI的事情。當線程結束時,我可以遞歸地設置Enabled = false,然後Enabled = true。但是這會忽略運行時的控制狀態(即由於各種原因禁用的控件將錯誤地重新啓用)。除了構建布爾樹之外,還有其他一些方法來阻止輸入(例如Java中的GlassPane類型)嗎?C#Winforms:在線程運行時選擇性地禁用UI

+0

有表單控件的屬性Opactity,根據你的設計,你可以使用一種形式通過設置不透明度爲有效地掩蓋另一種形式。 – Lloyd

回答

3

不要使用DoEvents,這是evil

使用面板並添加所有要在其中禁用的控件。當面板將被禁用時,所有內部控件將顯示爲禁用,但其屬性值不會被實際修改。

這裏有一個工作示例:

public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void button1_Click(object sender, EventArgs e) 
     { 
      // Disables UI elements using the panel 
      this.SetPanelEnabledProperty(false); 

      // Starts the background work 
      System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(this.Worker)); 
     } 

     private void Worker(object state) 
     { 
      // Simulates some work 
      System.Threading.Thread.Sleep(2000); 

      // Now the work is done, enable the panel 
      this.SetPanelEnabledProperty(true); 
     } 

     private void SetPanelEnabledProperty(bool isEnabled) 
     { 
      // InvokeRequired is used to manage the case the UI is modified 
      // from another thread that the UI thread 
      if (this.panel1.InvokeRequired) 
      { 
       this.panel1.Invoke(new MethodInvoker(() => this.SetPanelEnabledProperty(isEnabled))); 
      } 
      else 
      { 
       this.panel1.Enabled = isEnabled; 
      } 
     } 
    } 
1

您可以在腳本運行時使用填充了要禁用的控件的面板,然後在腳本結束時重新啓用面板。

或者,您可以爲腳本啓動Process

+1

+1對於使用包含面板 - 將面板的Enabled屬性設置爲false將禁用所有包含的控件,並將其設置爲true將恢復其原始狀態。比OP想到的遞歸方法好得多。 – Justin

0

您可以使用Application.DoEvents()方法解決此問題,或者您必須編寫調用相應控件的委託。 我認爲Application.DoEvents()將是最簡單的方法。 您應該在線程的循環中調用Application.DoEvents()。

爲代表的版本,你在這裏找到一些信息:http://msdn.microsoft.com/de-de/library/zyzhdc6b.aspx

+0

不要從除主UI線程之外的任何其他線程調用Application.DoEvents。你可能並不想提出這個建議,但你的回答在這個問題上並不十分清楚。 – Justin

+0

Application.DoEvents()將幫助您。在經常滴答的定時器內使用它 –