2011-01-06 11 views
8

Ich versuche, die Ursache eines lästigen Schnittstellenfehlers in einer App zu finden, die kürzlich von VS2003 auf VS2008 aktualisiert wurde (der Fehler existierte vor der Migration nicht). Was passiert ist das:Kann nicht leeres Textfeld entkommen

1) Der Benutzer klickt in ein Textfeld mit einem Datum.
2) Benutzer löscht Datum
3) Benutzer versucht, in ein anderes Feld zu verschieben, kann aber nicht. Es werden keine Fehlermeldungen angezeigt - als ob die Validierung fehlgeschlagen wäre.

Weitere Informationen:

1) Das Text-Eigenschaft des Textfeldes ist mit einem Dataview gebunden, die eine Datentabelle als Quelle verwendet. Das gebundene Feld ist ein Nullable-Datetime-Feld ohne Einschränkungen oder Standardwerte.
2) Das Validating-Ereignis wird ausgelöst und die CancelEventArgs-Eigenschaft wird nicht auf Cancel gesetzt. Die Validated-, LostFocus- und Leave-Ereignisse werden ebenfalls ausgelöst. LostFocus> Leave> Validieren
3) Ich kann mit ein paar Ausnahmen keine Codeänderungen in Bezug auf das Steuerelement oder die Datenquelle sehen. Der erste ist, dass das:

Me.txtRangeEnd.DataBindings.Add(New System.Windows.Forms.Binding("Text", Me.dvClientNos, "RangeEnd")) 

nun diese geändert hat:

Me.txtRangeEnd.DataBindings.Add(New System.Windows.Forms.Binding("Text", Me.dvClientNos, "RangeEnd", True)) 

Der zweite ist, dass das:

Me.dcolRangeEnd.DataType = GetType(System.DateTime) 

nun diese geändert hat:

Me.dcolRangeEnd.DataType = GetType(Date) 

Es gibt auch dieses, das in der Code seit dem ersten Tag:

AddHandler txtRangeEnd.DataBindings("Text").Format, AddressOf FormatBoxToDate 

Private Sub FormatBoxToDate(ByVal sender As Object, ByVal e As ConvertEventArgs) 
Try 
    If Not e.Value Is DBNull.Value Then 
      e.Value = Format(e.Value, "d") 
     End If 
    End Try 
End Sub 

Nun, wenn ich den „True“ aus dem Hinzufügen des Datenbindung entfernen, dann kann ich die Steuerung mit einem leeren Wert verlassen, aber es kehrt dann auf den ursprünglichen Wert. Das Entfernen der Datumsformatierung scheint hier keinen Unterschied zu machen (es wird nur auf den 06/01/2011 00:00:00 statt auf den gewünschten 06/01/2010 gezeigt). Kein anderer Code verweist auf diese Textbox. Ich denke, dass sich etwas bei der Validierung von datengebundenen Steuerelementen zwischen VS2003 und VS2008 geändert haben muss, aber es ist genauso wahrscheinlich, dass ich etwas, das wirklich offensichtlich ist, vermisse.

Irgendwelche Ideen?

Antwort

7

Der Grund dafür, dass Sie das beobachtete Verhalten sehen, liegt darin, wie Windows Forms und seine Datenbindung NULL-Datenbankwerte verarbeiten.

Der TL;DR Grund:

Sehen Sie diese Microsoft Connect-Vorschlag: Provide better databinding support for nullable types

Die lange Version:

Was im Wesentlichen geschieht, ist, dass, wie Sie deaktivieren Sie das Textbox (auf einen leeren string) und anschließend Register entfernt, an die Datenquelle der Bindung Ihren leeren String in einen DBNull Wert umzuwandeln, die dann die Bindung jedoch vermehrt wird, da es zwei ist -way, versucht dann, das gebundene Steuerelement (das Textfeld) mit entsprechender Formatierung erneut zu füllen, und schlägt fehl, was dazu führt, dass das Textfeld das seltsame Verhalten anzeigt, dass der Fokus nicht entfernt werden darf!

Dies geschieht aufgrund der DataSourceNullValue Eigenschaft der Binding class. Dies kann unter Verwendung einer der Bindungsklassen Konstruktorüberladungen eingestellt werden, oder separat über eine Eigenschaftseinstellung jedoch festgelegt, wenn Sie nicht explizit diese Eigenschaft festgelegt, ist es wichtig zu beachten, dass:

Die Standardeinstellung ist DBNull für Werttypen und Null für Nicht-Wert-Typen.

Es scheint, dass Sie dies nicht explizit Einstellung sind, so dass der Standard bewirbt, und mit Datetime ein value type sein, es DBNull verwendet.

Sobald die Datenquelle (auf DBNull) aktualisiert worden ist, wird der Bindungsmechanismus versucht, dann mit dem neu aktualisierten Datenquellen-Wert die Textbox zu besiedeln. Wenn der zugrunde liegende Datenquellenwert DBNull ist, wird der für das gebundene Steuerelement verwendete Wert von NullValue property der Binding-Klasse bestimmt. Auch wenn diese Eigenschaft nicht explizit entweder über das entsprechende überladene Konstruktor Argument oder über die Eigenschaft Einstellung selbst, der Standardwert gilt, das ist gesetzt:

Das Objekt gesetzt werden als Steuer Eigenschaft, wenn die Datenquelle enthält einen DBNull-Wert. Der Standardwert ist null.

Natürlich kann ein Textbox's Text property nur auf ein Objekt vom Typ System.String und keinem Null-Wert (Nothing in VB) eingestellt werden, so dass die TextBox nicht den repräsentativen Wert (null/nichts) der Daten binden Quellwert (DBNull) für das gebundene Steuerelement.

Die Möglichkeit, dieses Verhalten zu korrigieren ist, um sicherzustellen, dass die Binding class's NullValue property explizit auf einen geeigneten Wert eingestellt ist. In diesem Fall reicht eine Zeichenfolge mit der Länge Null aus, um das Problem zu beheben.

Eine Möglichkeit, dies zu erreichen, ist die Linie zu ändern:

Me.txtRangeEnd.DataBindings.Add(New System.Windows.Forms.Binding("Text", Me.dvClientNos, "RangeEnd", True)) 

zu:

Me.txtRangeEnd.DataBindings.Add(New System.Windows.Forms.Binding("Text", Me.dvClientNos, "RangeEnd", True, DataSourceUpdateMode.OnValidation, "")) 

Der Schlüssel hier ist der letzte Parameter, der die Nullvalue ist, auf einen null- length string (Die DataSourceUpdateMode wird auch explizit aufgrund der Argumente des Konstruktors angegeben, wird aber trotzdem auf den Standardwert gesetzt).

Trotz allem scheint es etwas "seltsames" Verhalten, wenn nicht ein tatsächlicher Fehler. Dies wird auch durch andere belegt, die das gleiche Problem zu haben scheinen (was in Visual Studio 2010/.NET 4.0 immer noch vorherrscht!). This thread auf den social.msdn.microsoft.com-Foren enthält jemanden, der das gleiche Problem mit einigen interessanten möglichen Erklärungen erfährt, warum dies geschieht, und warum Microsoft es so entworfen hat.

Es gibt auch eine , die im Jahr 2005 berichtet wurde, die das Problem hervorhebt. Dieser Vorschlag wurde "als verschoben abgelehnt". Es scheint, dass Microsoft es nicht als einen Fehler betrachtet, da eine sehr vernünftige Problemumgehung existiert (die explizite Einstellung der NullValue-Eigenschaft der Bindung), die aus Gründen der besseren Lesbarkeit sowieso getan werden sollte. Sie werden den Vorschlag in Zukunft offensichtlich berücksichtigen.

Zurück zu, warum dies nicht existierte pre.NET 2.0 (Visual Studio 2005) scheint aufgrund der Tatsache zu sein, dass der gesamte Datenbindungsmechanismus für die Veröffentlichung von .NET Framework 2.0 vollständig überarbeitet wurde. Ihre ursprüngliche Lösung, bei der es sich um ein VS2003-Projekt handelte, verwendete .NET Framework 1.1, das nicht über ein so umfangreiches Datenbindungs-Feature-Set verfügte. Obwohl ich keine Kopie von VS2003 mehr zur Hand habe, um das zu testen, nehme ich an, dass der Bindungsmechanismus in .NET 1.1 viel mehr implizite Konvertierungen zwischen dem Wert des Steuerelements und dem Wert der Datenquelle verwendet. Diese wird unterstützt, wenn Sie die Binding-Klasse von .NET 1.1, verglichen mit .NET 2.0 (oder höher) unterstützt werden. Zum Beispiel gab es keine Möglichkeit, die tatsächliche Zweiwege-Bindung selbst (und wie Werte zwischen dem Formular und der Datenquelle konvertiert werden) oder die Formatierung dieser Werte (einfach) zu steuern.

+0

Diese kleine FormatBoxToDate-Methode wurde tatsächlich erstellt, da .NET 2003 keine andere Möglichkeit hatte, dies zu tun. Die NULL-Wert-Eigenschaft ist jetzt über das Menü Erweiterte Datenbanken verfügbar. Wenn Sie jedoch versuchen, dies über die IDE auf eine leere Zeichenfolge zu setzen, wird der Wert im Code auf Nothing gesetzt, was keinen Unterschied macht. – MartW

+0

Ich habe es stattdessen manuell zu String.Empty gehackt (nie gemocht "") und es funktioniert jetzt. Ich nenne das gut verdiente Bounty: D – MartW

+0

Sehr alt, aber sehr nützlich, da es immer noch in VS2013 gilt! aber Nebenfrage: die Linie zu ändern, arbeitete großartig für mich .. aber ich habe alles andere in den Designer-Eigenschaften gepflegt .. wenn ich es richtig verstehe, ist es eine Frage des Hinzufügens der Null-Wert im Folgenden unter den Textfeld Eigenschaften -> (Datenbindungen) -> (Erweitert) -> wähle die Texteigenschaft, wähle ein Datumsformat (in meinem Fall) und fülle dann den Nullwert aus. Ein leerer String scheint dort jedoch nicht zu funktionieren. irgendwelche Tipps, wie man es im Designer macht? –

0

Ich hatte diese Art von Fehler zuvor und ich musste sicherstellen, dass die zugrunde liegende Datenquelle (in meinem Fall war es ein Dataset) wurde nicht auf schreibgeschützt festgelegt und dass die Spalte zulässig Null-Werte.

Sobald ich das getan hatte, hat alles gut funktioniert. Es schien, als ob der Fehler, der in den Datenbindungen geworfen wurde, irgendwo verschluckt wurde und sich nicht ausbreitete.

Verwandte Themen