Erstellt man in WinForms eine Form
oder ein UserControl
, so können deren Properties und Elemente komfortabel über den Designer in Visual Studio angepasst werden. Wird das jeweilige Element geöffnet, so führt der Designer dabei den Konstruktor der Form
aus und bezieht die darin durchgeführten Aktionen mit in die Darstellung ein.
Dieses Verhalten führt dann zu Problemen, wenn im Konstruktor z.B. Datenquellen angesprochen werden, um die UI zur Laufzeit beim Erstellen der Form
bzw. des Control
s aufzubauen. Zur Design-Zeit löst dies i.d.R. Exceptions aus, die ein Laden der Form
/des Controls
verhindern.
Der erste Versuch: DesignMode
Jede Form
und jedes UserControl
sind in eine Vererbungshierarchie eingebettet. Beide leiten indirekt von Control
ab, das von Component
erbt. Component
besitzt ein boolesches Property DesignMode
, über das im Konstruktor entschieden werden kann, ob die jeweilige Komponente aktuell im Designer geöffnet wird oder nicht. Dementsprechend lässt es sich dazu verwenden, um nur gewünschte Operationen zur Design-Zeit im Konstruktor auszuführen:
1: public MyForm()
2: {
3: InitializeComponent();
4:
5: // Aktionen, die immer ausgeführt werden sollen
6: // ...
7:
8: if (DesignMode)
9: return;
10:
11: // Aktionen, die nur zur Laufzeit ausgeführt werden sollen
12: // ...
13: }
Das Ganze funktioniert solange, wie man die Form
bzw. das Control
direkt im Designer öffnen will. Gerade bei UserControl
s ist es aber viel häufiger der Fall, dass sie in andere Controls bzw. Formulare eingebettet sind, die man öffnen möchte. Leider greift DesignMode
in diesem Fall nicht, das dann als Wert false hat. DesignMode
hilft demnach nur, wenn das Control direkt im Designer geöffnet wird.
Abhilfe: Der LicenseManager
Abhilfe für dieses Problem schafft die sealed class LicenseManager
aus dem Namespace System.ComponentModel
. Das statische Property LicenseManager.UsageMode
lässt sich dazu verwenden, um den aktuellen Darstellungsmodus auch bei eingebetteten Aufrufen ermitteln zu können. Die Lösung des Problems sieht demnach so aus:
1: public MyForm()
2: {
3: InitializeComponent();
4:
5: // Aktionen, die immer ausgeführt werden sollen
6: // ...
7:
8: if (LicenseManager.UsageMode == LicenseUsageMode.Designtime)
9: return;
10:
11: // Aktionen, die nur zur Laufzeit ausgeführt werden sollen
12: // ...
13: }
Diese Lösung kann dazu verwendet werden effizient die Ausführung von Aktionen im Konstruktor zu verhindern oder beispielsweise auch um DesignTime-Daten an die UI zu binden.