2008-11-11 33 views
10

我有一個對象,啓動一個線程,打開一個文件,並等待來自其他類的輸入。當它接收到輸入時,它將它寫入磁盤。基本上,它是一個線程安全的數據記錄類....NET的Windows窗體設計時間規則

這是奇怪的部分。當我在設計器中打開一個窗體(Visual   Studio   2008)時,會使用該對象創建文件。這顯然運行在設計時間虛擬主機進程...

奇怪的是我一直無法在另一個項目中重現問題。我不確定在設計器中執行的代碼和不執行代碼的規則是什麼。例如,在Windows窗體構造函數中創建文件實際上並不會在設計時創建文件...

什麼是解釋?有參考嗎?

回答

11

您可以檢查LicenseManager的UsageMode,檢查代碼是否在設計時。

System.ComponentModel.LicenseManager.UsageMode == System.ComponentModel.LicenseUsageMode.Designtime

下面是一個簡單的例子:

using System; 
using System.ComponentModel; 
using System.Windows.Forms; 

namespace Test 
{ 
    public class ComponentClass : Component 
    { 
     public ComponentClass() 
     { 
      MessageBox.Show("Runtime!"); 
     } 
    } 
} 

當此組件獲得添加到您的窗體設計器中,您將馬上得到一個消息框。

爲了防止這種情況,你可以添加一個簡單的if語句來檢查代碼是不是在設計時

using System; 
using System.ComponentModel; 
using System.Windows.Forms; 

namespace Test 
{ 
    public class ComponentClass : Component 
    { 
     public ComponentClass() 
     { 
      if (LicenseManager.UsageMode != LicenseUsageMode.Designtime) 
      { 
       MessageBox.Show("Runtime!"); 
      } 
     } 
    } 
} 

添加if語句後,將組件添加到窗體的消息框不再出現通過設計師。

我希望這會有所幫助。

-jeremy

0

有些事情你不應該與設計師做。我沒有任何確鑿的證據,但是我發現Windows窗體設計師在從中取出默認構造函數時會討厭它。只要繼續並創建新的重載,但留下空的構造函數就位。

還嘗試避免在您繼承的基類中執行事件。

2

你也可以用它來檢查,如果在Visual Studio設計器運行代碼:

public static bool DesignMode 
{ 
    get { return (System.Diagnostics.Process.GetCurrentProcess().ProcessName == "devenv"); } 
} 

然後在的Form_Load:

if (!DesignMode) 
{ 
    // Run code that breaks in Visual Studio Designer (like trying to get a DB connection) 
} 

然而,這是少優雅比使用LicensManager.UsageMode,但它的作品(直到微軟更改Visual Studio運行的進程的名稱)。

+0

男人,你的「不那麼優雅」的方法是唯一可行的方法。 LicensManager.UsageMode不起作用,例如當設計者調用用戶控件的「屬性獲取」方法時。 – Soonts 2010-06-10 16:11:45

11

在設計器中編輯該類時(即使OnLoad被調用),控件或表單的構造函數也不會被執行。我偶爾會使用它在設計器中設置一個值(例如,使其子控件在設計器中全部可見),但在構造函數中將其中的一些重寫爲不同的默認值(例如,隱藏某些僅顯示在某些情況下,例如狀態欄上的指示器)。

但是,構造函數確實如果將控件作爲子控件放置在設計器中的另一個控件或窗體上,則會被執行。 OnLoad也會被執行。這可能是您的日誌代碼在設計器中意外觸發的原因。

對於檢測設計與運行時間,an answeranother question有一些經驗測試的屏幕截圖顯示了一些常用方法返回的值。看起來,在設計器中編輯的窗體或控件的子控件的子控件會看到它自己的DesignMode == false,因此正常的屬性檢查將無法保護代碼(例如,在OnLoad方法中)嵌套在設計器中添加的控件中的控件。如果您按照預期的方式檢查DesignMode,則可能是嵌套導致它繞過該檢查。它總是在構造函數中看到DesignMode == false。

另外,請注意,LicenseManager.UsageMode檢查只有在構造函數中看到DesignTime;當調用OnLoad時,它在RunTime LicenseContext中。最完整的解決方案似乎是檢查控件或表單(或組件)的構造函數中的LicenseManager.UsageMode,並將設置保存到一個成員變量或屬性中,稍後可以檢查該成員變量或屬性以避免運行不應該在設計器中運行的代碼即使嵌套。 another answer中還有另一個解決嵌套的問題,但只能在構造函數之外使用。

+0

我認爲這可以幫助我。謝謝! ++ – John 2011-11-29 17:37:18

2

好了,因爲這已經反正復活了,這是我用它來確定我是否在設計模式功能:

public static bool IsAnyInDesignMode(Control control){ 
    while(control != null){ 
     if(control.Site != null && control.Site.DesignMode) 
      return true; 
     control = control.Parent; 
    } 
    return false; 
} 

此處理這樣的控制是由其他控件創建一個孩子的情況下。 DesignMode屬性僅爲設計者自己創建的控件設置。