設計階段開發疑難排解
下列常見問題可能會在您為 Windows Form 元件和控制項建立自訂設計階段經驗時發生。
無法編譯
無法在設計階段偵錯
編譯錯誤:「找不到型別或命名空間名稱 'type name'。」
設計階段錯誤:「無法建立元件 'component name'。」
偵錯錯誤:「不合法的跨執行緒作業:控制項 'control name' 是從所建立執行緒之外的其他執行緒存取。」
設計階段錯誤:「因為檔案中的類別並非繼承自可用視覺設計方式設計的類別,所以無法開啟該檔案的設計工具。」
刪除了元件之後圖像 (Glyph) 還在
自訂行為遮蔽了預設的設計工具行為
無意之間引發了設計工具事件
集合無法序列化
設計工具無法取得 UndoEngine 參考
設計環境無法識別對元件屬性所作變更
變更元件或設計工具之後重新整理設計環境
FxCop 對新產生的 Windows Form 之警告:DoNotInitializeUnnecessarily
部分類別和 Windows Form 設計工具
舊版的自訂控制項在設計工具內產生非預期的行為
裝載之設計工具內的智慧標籤引發例外狀況
元件圖示沒有顯示在工具箱中
無法編譯
在設計階段開發中,絕大部分都必須加入設計階段組件 (System.Design.dll) 的參考。 這個組件未包含在 .NET Framework 4 Client Profile 中。 若要加入對 System.Design.dll 的參考,您必須將專案的目標 Framework 變更為 [.NET Framework 4]。
無法在設計階段偵錯
偵錯設計階段程式碼有下列兩種方式:
在程式碼的策略位置呼叫 MessageBox.Show。
附加另一個 Visual Studio 執行個體,為第一個執行個體的設計環境進行偵錯。
如需詳細資訊,請參閱 HOW TO:存取設計階段服務。
編譯錯誤:「找不到型別或命名空間名稱 'type name'」
您必須參考 System.Design 組件。 與設計工具相關的型別是位於 System.Design 組件中。 這包括 System.Windows.Forms.Design 和 System.ComponentModel.Design 命名空間中的型別。
同時務必要使用 Imports 或 using 關鍵字,匯入所需的命名空間。 如需詳細資訊,請參閱 HOW TO:在 Windows Form 中存取設計階段支援。
設計階段錯誤:「無法建立元件 'component name'」
從 [工具箱] 在設計介面上建立元件或控制項時,您可能會接到這個錯誤訊息。 下表會說明兩種可能造成這項錯誤的原因。
原因 |
描述 |
備註 |
---|---|---|
遺漏預設建構函式 |
您的元件或控制項必須有預設建構函式,它是沒有參數的建構函式。 |
設計環境需要預設建構函式,才能建立型別的執行個體。 |
元件是泛型型別 |
您的元件或控制項不能為「泛型」型別,也稱為「樣板」型別或「參數化」型別。 設計環境不支援泛型型別。 |
如果您的泛型型別是衍生自 UserControl,而您嘗試要在 Visual Studio 的 [使用者控制項測試容器] 中執行,將會接到下列錯誤訊息: 建立使用者控制項 (UserControl) 'name' 失敗 錯誤訊息為「無法建立 Type.ContainsGenericParameters 為 true 的型別」。 UserControl 將從清單中移除。 雖然您的元件和控制項本身不能為泛型型別,但可以使用泛型型別。 |
設計階段錯誤:「值不能為 null。參數名稱:'component name'」
從 [工具箱] 在設計介面上建立元件或控制項時,您可能會接到這個錯誤訊息。 最可能造成這項錯誤的原因是:您嘗試要使用建置至 64 位元組件上的元件或控制項。 Visual Studio 設計環境並不支援 64 位元元件。
偵錯錯誤:「不合法的跨執行緒作業:控制項 'control name' 是從所建立執行緒之外的其他執行緒存取。」
如果在 Windows Form 應用程式中使用多執行緒處理,以安全執行緒方式呼叫控制項時必須特別小心。 這種例外狀況是由偵錯工具引發,而不會出現在執行階段,但是極力建議您,看到這個問題時一定要加以修正。 如需詳細資訊,請參閱 HOW TO:進行對 Windows Form 控制項的安全執行緒呼叫。
設計階段錯誤:「因為檔案中的類別並非繼承自可用視覺設計方式設計的類別,所以無法開啟該檔案的設計工具」
元件或控制項所附的檔案可以包含多個類別定義,但是檔案中的第一個類別必須是您可以設計的類別。 檔案中的第一個類別必須實作 IComponent 介面,或者必須衍生自 Component 類別或衍生 Component 的類別。
刪除了元件之後圖像 (Glyph) 還在
如果自訂設計工具建立了任何 Adorner 物件,必須在設計工具超出範圍時,從設計介面刪除。 呼叫設計工具之 Dispose 方法中的 BehaviorServiceAdornerCollection.Remove,以清除 Glyph 物件以及相關聯的 Adorner 和 Behavior 物件。 如需詳細資訊,請參閱 HOW TO:在設計模式中擴充控制項的外觀和行為。
自訂行為遮蔽了預設的設計工具行為
預設控制項設計工具建立了圖像,涵蓋設計介面上的整個控制項。 這稱為「主體圖像」。 如果自訂控制項設計工具以與主體圖像相同的界限建立圖像,則將遮蔽與主體圖像相關聯的基礎 Behavior 實作。 這樣智慧標籤及調整圖像大小等預設功能就會無法顯示。
您不能在 Behavior 物件之間傳遞訊息,因此也不能處理滑鼠訊息,並轉送至任何基礎的 Behavior 物件。 當您實作涵蓋整個控制項的圖像時,就必須負責自訂設計經驗的整個外觀和行為。
無意之間引發了設計工具事件
如果自訂設計工具附加事件處理常式至設計工具事件,例如 ComponentRemoved、ActiveDesignerChanged 和 SelectionChanged,則必須中斷設計工具之 Dispose 方法中的事件處理常式連結。
如果沒有中斷連結,可能會在執行階段造成意外行為。 下列清單中列出一些可能會發生的狀況:
錯誤訊息方塊:「處理這個命令時發生錯誤。」
錯誤訊息方塊:「物件參考未設定到物件的執行個體。」
已刪除元件或已關閉設計工具之後,不正確地呼叫事件處理常式。
集合無法序列化
如果要將自訂元件或控制項的集合屬性序列化,請套用 DesignerSerializationVisibilityAttribute,並將它設定為 Content。 如需詳細資訊,請參閱 HOW TO:使用 DesignerSerializationVisibilityAttribute 序列化標準型別的集合。
設計工具無法取得 UndoEngine 參考
如果嘗試在載入表單時取得 UndoEngine 服務的參考,GetService 方法會傳回 null。
UndoEngine 服務一直要到表單完成其載入階段之後才會建立並啟用。 載入表單之後,後續呼叫 GetService 將傳回 UndoEngine 參考。
一般來說,很少會需要直接參考 UndoEngine。 確實需要直接參考的情況通常是因使用者動作而引發,而會發生在載入設計工具之後。
設計環境無法識別對元件屬性所作變更
如果直接設定屬性,設計環境就無法識別對元件或控制項所作的變更。 若要引發像 ComponentChanged 之類的事件,必須利用 PropertyDescriptor.SetValue 方法設定元件的屬性值。 這樣才會將屬性變更告知設計環境,而讓設計介面和 PropertyGrid 控制項正確地更新。 如需詳細資訊,請參閱 HOW TO:在設計模式中擴充控制項的外觀和行為。
DesignerAttribute 語法
您可以透過套用 DesignerAttribute 至控制項,將自訂設計工具附加至所設計的控制項。
您必須精確地指定 DesignerAttribute 參數,否則設計環境將不會載入您的自訂設計工具。
變更元件或設計工具之後重新整理設計環境
當您對元件的設計階段方面進行變更時,必須重新建置元件的專案。 此外,如果目前有開啟另一個 Windows Form 專案,而且該專案使用這個元件,您可能需要重新整理專案才能看到變更。 您通常必須先關閉包含元件的設計視窗,然後再重新開啟。
FxCop 對新產生的 Windows Form 之警告:DoNotInitializeUnnecessarily
Windows Form 設計工具會為 C# Windows Form 應用程式專案產生下列程式碼。
private System.ComponentModel.IContainer components = null;
依作用中的 FxCop 規則而定,FxCop 可能會產生 "DoNotInitializeUnnecessarily" 警告。 這是因為 null 是參考屬性的 Common Language Runtime (CLR) 預設值。
如果設計工具未將 components 欄位初始化為 null,C# 編譯器就會產生下列警告:
「一直未指派欄位 Form1.component,將一直讓其預設值維持為 null。」
您可以利用 SuppressMessageAttribute 隱藏 FxCop 警告,但如果類別名稱變更,這樣可能會造成維護的問題。 因此,建議您忽略 FxCop 警告。
部分類別和 Windows Form 設計工具
Windows Form 設計工具預設為發出設計工具序列化程式碼,送入與元件的主檔案分開的專屬檔案中。 例如,在 Windows Form 應用程式專案中,Form1 類別的定義分成兩個檔案,如下表所示。
檔案 (C# 檔案名稱) |
功能 |
---|---|
Form1.cs |
主類別檔案 |
Form1.Designer.cs |
設計工具發出的程式碼 |
檔案 (VB 檔案名稱) |
功能 |
---|---|
Form1.vb |
主類別檔案 |
Form1.Designer.vb |
設計工具發出的程式碼 |
一般而言,您不需要修改 Windows Form 設計工具所發出的程式碼, 而是要編輯主要類別檔。
Windows Form 設計工具使用 partial 關鍵字,將 Form1 的實作分成兩個不同的檔案。 這樣可以防止設計工具發出的程式碼與您的程式碼位置顛倒。 如需 partial 關鍵字的詳細資訊,請參閱 部分類別和方法 (C# 程式設計手冊) 和 Partial (Visual Basic)。
Windows Form 設計工具不支援將可設計型別的定義分割成兩個以上的 partial 實作。 這項限制包括建立新的類別檔案,其中包含第三個部分型別定義,以及在主檔案或設計工具檔案中加入第三個部分類別定義。 以這種方式定義的成員將無法在 Windows Form 設計工具中看見。
舊版的自訂控制項在設計工具內產生非預期的行為
當型別在設計工具內失效時,ComponentSerializationService 會執行「部分重新載入」(Partial Reload),以更新的型別重新整理設計工具。 在 Visual Studio 2005 之前的 Visual Studio 版本會完整地重新載入設計工具; Visual Studio 2005 內的部分重新載入行為會比完整重新載入的速度更快,並且也保留了復原堆疊。
在 Visual Studio 2005 之前撰寫的元件和對應之序列化程式可能無法提供部分重新載入功能, 因為這些元件和控制項設計為只有在完整重新載入時會還原序列化,所以可能會導致非預期的行為。 當有舊版控制項存在時,出現的徵兆包括堆疊溢位 (Stack Overflow)、當機,或是在 Windows Form 設計工具內出現空白區域。
您可以在 devenv.exe.config 檔案內加入下列設定,還原成完整重新載入的行為。 如果您在預設位置安裝 Visual Studio 2005,則這個檔案會位於 C:\Program Files\Microsoft Visual Studio 8\Common7\IDE 資料夾中。
<appSettings>
<add key="EnableOptimizedDesignerReloading" value="false" />
</appSettings>
裝載之設計工具內的智慧標籤引發例外狀況
如果您正在 Visual Studio 外部裝載 (Host) 設計工具,您的智慧標籤可能會引發 NullReferenceException。 若要解決這個問題,請在設計工具內提供 IUIService 參考,並實作 Styles 屬性。 在由 Styles 公開 (Expose) 的 IDictionary 中,指派新的 Font 當做 "DialogFont" 機碼所指定的項目,如下列程式碼片段所示。
Styles["DialogFont"] = new Font(...);
元件圖示沒有顯示在工具箱中
在 Visual Studio 中,當您使用 ToolboxBitmapAttribute 以產生圖示與自訂元件之間的關聯時,點陣圖並不會顯示在自動產生之元件的工具箱上。 若要看到點陣圖,請使用 [選擇工具箱項目] 對話方塊重新載入該控制項。 如需詳細資訊,請參閱工具箱圖示。