WinForms: Aktionsausführung im Designer verhindern

27. Oktober 2010

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 Controls 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 UserControls 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.