(View this article in Google-translated English)
Dieser Artikel hier soll mein Versuch werden, verschiedene Fehlermeldungen im leider nicht perfekten C#-Windows Forms-Designer von Visual Studio.NET 2005 zu interpretieren und möglichst zu lösen.
Ich werde den Artikel nach und nach um alle im Laufe der Zeit bei mir so auftretenden Fehlermeldungen und möglichst auch Lösungen ergänzen.
1.) Fehlermeldungen aufgrund von Fehlern im eigenen Code
Der Windows Forms-Designer ruft auch während des Designens Code auf den Ihr geschrieben habt (Details habe ich nie erforscht, welchen und was er ausführt, aber zumindest der Konstruktor des Forms wird aufgerufen).
Deshalb kann es vorkommen, dass Code von Euch Ausnahmen werfen, die wiederum im Designer dann sichtbar werden und ein graphisches Arbeiten verhindern. Z.B. nachfolgendes Bildschirmfoto:
Bildschirmfoto 1: Fehlermeldungen im Form-Designer (Klick für Großbild)
Textuell kommt folgende Fehlermeldung:
Object reference not set to an instance of an object.
at System.ComponentModel.ReflectPropertyDescriptor.SetValue(Object component, Object value)
at System.ComponentModel.Design.Serialization.CodeDomSerializerBase. DeserializeAssignStatement( IDesignerSerializationManager manager, CodeAssignStatement statement )
at System.ComponentModel.Design.Serialization.CodeDomSerializerBase. DeserializeStatement( IDesignerSerializationManager manager, CodeStatement statement )
Wichtig zu verstehen ist, dass es eine beliebige Fehlermeldung sein kann, nicht nur die hier oben angegebene Null-Referenz-Ausnahme.
In meinem Beispiel war folgendes die Ursache:
Ich habe in dem Form eine eigenes Benutzer-Steuerelement („UserControl“) verwendet, das im Designermodus eine Ausnahme ausgelöst hat, und zwar beim Zuweisen einer Eigenschaft.
Der Grund für diese Ausnahme im Steuerelement war, dass zur Laufzeit gewisse Ereignis-Behandlungsroutinen aufgerufen werden (z.B. das „Load“-Ereignis des Formulars) und in diesen Behandlungsroutinen dann Variablen initialisiert werden.
Im Designmodus werden diese Behandlungsroutinen nun eben nicht aufgerufen und die Variablen eben nicht initialisiert. Deswegen hat dann die Eigenschaft eine Ausnahme ausgelöst.
Auch wenn im Designer-Fenster keine genaue Fehlerposition angegeben wurde, so zeigte die „Error List“ die genaue Position an, und zwar in Form einer „Warning“ (siehe Bildschirmfoto oben).
Ein Doppelklick auf die „Warning“-Liste öffnete dann die „*.designer.cs“-Quelltextdatei und zeigte wo der Fehler war. In meinem Beispiel war das die Zeile
this.imageControl.ImageObjectID = null;
Ein beherzter Rechtsklick mit der Maus auf ImageObjectID
und dann „Go to Definition“ öffnete dann den Quelltext der ImageObjectID
-Eigenschaft meines Benutzer-Steuerelements im Editor. Darin war also irgendwo der Fehler.
Lösung:
Oftmals war es für mich gar nicht nötig den genauen Fehler zu lokalisieren, da dieser ja nur im Designmodus auftrat; zur Laufzeit verhielt sich die Anwendung korrekt.
Deswegen habe ich mir eine statische Methode geschrieben die prüft, ob ein Steuerelement im Designmodus ist:
/// <summary> /// Checks whether a control or its parent is in design mode. /// </summary> /// <param name="c">The control to check.</param> /// <returns>Returns TRUE if in design mode, false otherwise.</returns> public static bool IsDesignMode( Control c ) { if ( c == null ) { return false; } else { while ( c != null ) { if ( c.Site != null && c.Site.DesignMode ) { return true; } else { c = c.Parent; } } return false; } }
Diese Funktion, zentral abgelegt, rufe ich immer dann auf, wenn ich einen Codeblock quasi für den Designmodus „auskommentieren“ möchte, also eben nicht ausführen.
Ein Bisschen ein Hack, aber sehr effektiv und funktionierend.
Alternative Lösung:
Wenn Eigenschaften nicht zur Laufzeit gesetzt werden müssen, folgende Attribute an die Eigenschaft anhängen:
[Browsable(false)] [EditorBrowsable(EditorBrowsableState.Never)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
Das sorgt dafür, dass der Designer die Eigenschaften komplett in Ruhe lässt.
Falls Ihr nachträglich diese Attribute setzt, müsst Ihr in den Designer-Dateien bereits vorhandene unnötige Zuweisungen zu den Eigenschaftswerten entfernen, damit es im Design-Modus funktioniert.
2.) Ein Form das im Designer geöffnet wird ist leer und zeigt keine Steuerelemente mehr an
Ich hatte einige wenige Male das Phänomen, dass ein bereits funktionierendes Formular mit zahlreichen Steuerlementen auf einmal beim Öffnen im Form-Designer komplett leer war.
Bildschirmfoto 2: Leeres Form im Form-Designer (Klick für Großbild)
Ein Blick in die „*.designer.cs“-Datei des Forms zeigte dann, dass ganz am Ende der Funktion InitializeComponent
eine oder beide dieser Zeilen fehlte:
this.ResumeLayout( false ); this.PerformLayout();
Nachdem ich diese ergänzt hatte, das Form wieder geschlossen, neu kompiliert und geöffnet hatte, war alles wieder im Form-Designer vorhanden und auch zur Laufzeit voll funktionsfähig. Manchmal reicht auch schlicht das Ergänzen der fehlenden Zeile, ohne ein Neukompilieren.
Bildschirmfoto 3: Korrekt gefülltes Form im Form-Designer (Klick für Großbild)
Die Ursache warum der Form-Designer den Code gelöscht hat ist mir leider unbekannt.
Bei meinen Fällen war danach auch der Code dauerhaft vorhanden. Jörg hat leider die Erfahrung gemacht, dass nach jedem manuellen Einfügen und Schließen der Datei, der Form-Designer den Code erneut gelöscht hat. Bei Jörg war es ein Formular mit sehr vielen Steuerelementen (ca. 200), ggf. könnte(!) das eine Ursache gewesen sein.
3.) Die Zuordnung der Eigenschaften Form.AcceptButton
und Form.CancelButton
gehen verloren
Relativ oft passiert es mir, dass ich einem Form im Form-Designer via Eigenschaftsfenster die Werte für Form.AcceptButton
und Form.CancelButton
zuweise (also die Schaltflächen die beim Benutzen der Eingabetaste bzw. der Escape-Taste ausgelöst werden) und irgendwann die Zuordnungen wieder verschwunden sind.
Die genaue Ursache kann ich leider nicht ermitteln, mir ist aber aufgefallen wenn ich Änderungen im Form-Designer Rückgängig mache (über Strg+Z oder den „Rückgängig“-Eintrag im „Bearbeiten“-Menü), die Zuordnung auch verschwindet. Ggf. hängt das damit zusammen.
Dieser Punkt ist jetzt nicht mission critical, aber dennoch lästig, weil es halt nicht sofort auffällt.
Manchmal bin ich jetzt dazu übergegangen, im Konstruktor eines Form, nach dem automatisch generierten Aufruf zu InitializeComponent()
die Zuordnungen manuell hinzuschreiben, so dass diese dauerhaft erhalten bleiben.
4.) Die Schaltflächen (ToolStripItem
s) einer Werkzeugleiste (MenuStrip
) werden nicht mehr dargestellt
Diesen Effekt hatte Kollege Thilo einmal gehabt, mit dem Ergebnis, dass die Werkzeugleiste komplett „leer“ dargestellt wurde.
Es ist nach einem Absturz der Visual Studio .NET 2005-IDE aufgetreten.
Im Endeffekt haben einige Zuordnungen in der „*.designer.cs“-Quelltextdatei gefehlt.
So sahen die relevanten Zeilen direkt nach dem Absturz aus:
... // // toolStrip1 // this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.toolStripSeparator1, this.toolStripSeparator2, this.toolStripSeparator3}); this.toolStrip1.Location = new System.Drawing.Point(0, 24); this.toolStrip1.Name = "toolStrip1"; this.toolStrip1.Size = new System.Drawing.Size(809, 25); this.toolStrip1.TabIndex = 5; this.toolStrip1.Text = "toolStripMain"; ...
Und so die manuell korrigierte, wieder funktionierende Version:
... // // toolStrip1 // this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.btnPublish, this.toolStripSeparator1, this.btnPGedit, this.btnPGadd, this.btnPGdel, this.toolStripSeparator2, this.btnAGedit, this.btnAGadd, this.btnAGdel, this.toolStripSeparator3, this.btnAedit, this.btnAadd, this.btnAdel}); this.toolStrip1.Location = new System.Drawing.Point(0, 24); this.toolStrip1.Name = "toolStrip1"; this.toolStrip1.Size = new System.Drawing.Size(809, 25); this.toolStrip1.TabIndex = 5; this.toolStrip1.Text = "toolStripMain"; ...
Thilo konnte das aus einer Sicherheitskopie (auch „Backup“ genannt) wiederherstellen.
An dieser Stelle mal der erneute Hinweis, wie wichtig Sicherheitskopien sind!
Ich „zippe“ mir immer mal wieder komplette Projektstände und speichere sie mit Datum versehen in einen Ordner (z.B. mit dem Dateinamen „myproject – 2006-07-18.zip“), so dass ich auch mehrere Schritte zurückgehen kann.
Hello from the United States!! 🙂
Omni
Na super, sofort löschen, der Kommentar passt null zum Thema!
Neee, ich bin tolerant!
Hmmm, ich habe es ab und zu, dass der Designer beim „Rückgängig“ machen das ganze Formular leert. Und zwar wenn ich ein Event hinzugefügt habe und dann STRG+Z mache ist das Form weg.
Lösung: In der Eventhandler Liste nach dem neuen suchen und diesen von Hand entfernen.
Irgendwie habe ich beim aktuellen VS das Gefühl ein unfertiges Produkt zu benutzen.
Irgendwie habe ich bei allen Softwareprodukten dieses Gefühl :-).
Aber daß es kaum Doku/Samples gibt zu Windows Forms, das macht mir mehr sorgen.
Hy, habe Deinen Trick mit der Site.DesignMode ausprobiert. Bei mir ist Site bei allen Controls bis ganz oben immer null. Daher komme ich an den DesignMode auf keiner Ebene heran.
Was mache ich falsch?
Cu
Volker
Habs gestern auch noch mal benutzt, und hat auch nicht geklappt :-(.
Entweder gings noch nie und es fiel mir nie auf, oder nur in dem Fall nicht. Muß ich nochmals recherchieren.
Bin inzwischen einen Schritt weiter. Die Controls, die im Designer angezeigt werden können, verfügen offenbar selbst über ein DesignMode-Property, welches funktioniert.
Bei meiner Konstellation ist es so, dass sich Controls und die Form, in welcher die Controls eingesetzt werden, im gleichen Projekt befinden. Die Form ist in diesem Fall sogar die Haupt-Form, die statisch in program.c initialisiert wird.
Da die DesignMode Eigenschaft beim Control nur true anzeigt, wenn das Control selbst im Designer geändert wird, nicht aber wenn die Haupt-Form geändert wird (und genau das ist ja das Problem), habe ich eine Globale Klasse wie folgt erstellt:
Eine statische Variable enthält eine Referenz auf die Haupt-Form. Diese Referenz wird in program.c mit der Haupt-Form gefüllt, bevor die Haupt-Form angezeit wird.
Zum anderen gibt es ein statisches Property, welches InDesignMode heißt und für den Fall, dass die Variable != null ist ein false, ansonsten ein true zurückliefert.
Jetzt frage ich im Control nicht this.DesignMode sondern Globals.InDesignMode ab und schon geht’s.
Ciao
Volker Lehnen
Sauguter Tipp. Danke fürs Erforschen und die Info hier, Volker!
Moin,
ich habe genau das Probelm das in 2.(Ein Form das im Designer geöffnet wird ist leer und zeigt keine Steuerelemente mehr an). Leider hilft der hier gezeigte Fix bei mir nicht.
Hat da jemand noch eine andere Idee??
Viele Grüß!
Ich arbeite gerne mit VS2005. Eigene UserControls zu entwickeln, die dann auch noch während der Designtime
ausgeführt, werden ist sehr flexibel. Ich möchte jetzt im UserControl den Dateinamen der Solution haben, um dynamisch auf andere Komponenten in der Solution zugreifen zu können. EnvDTE80.DTE2 würde solche Methoden haben, aber ich kann keine Verbindung zwischen UserControl und DTE2 herstellen.
Hat jemand eine Idee?
Vielleicht irgendwelche „IEnvironment“-Schnittstellen, falls es so was gibt? Ggf. via Reflection und so?
hi, ich kann meine programme in c# gar nicht ausführen, es kommt immer die fehlermeldung: „fehler beim ausführen des projekts: das debuggen kann nicht gestartet werden. die bindungsnummer ist unzulässig.“
kenn mich auch nicht so gut aus mit dem ganzn zeug, bin also quasi ein neuling. bitte um hilfe
Hi,
endlich hat sich mal jemand erbarmt um sich diesem Thema anzunehmen. Dein tipp mit den Warnings hat mir enorm geholfen.
vielen vielen dank.
Gerne doch! Kommst mal vorbei, dann schauen wir, wie Du Dich revanchieren kannst. Har har.
Hi,
danke für die Tipps. Habe zu 1.) auch gerade viel rumgeforscht, das ist ja wohl ein größeres Problem, das aber sehr selten behandelt wird. Danke noch mal.
Gerne. Jetzt aber husch-husch das Update auf VS.NET 2008 durchführen 😉