Validierung funktioniert nur einmal

  • WPF

Es gibt 6 Antworten in diesem Thema. Der letzte Beitrag () ist von kaifreeman.

    Validierung funktioniert nur einmal

    Hallo Forum,

    Ich bin gerade dabei mit in das Thema WPF zu stürzen und habe derzeit ein Problem mit der Validierung von WPF.

    Das Programm (ein simples Haushaltsbuch zum üben) hat eine SQL Express Datenbank die Datasets sind im Studio angelegt und die Datenbindungen definiert mein Problem ist das die Validierung nicht funktioniert
    ich habe zum Beispiel das Feld "Buchung" das auf das Datenfeld "amount" gebunden ist:

    XML-Quellcode

    1. <TextBox x:Name="AmountTextBox" Grid.Column="1" Height="25" Width="235" Grid.Row="2" PreviewTextInput="AmountTextBox_TextInput" VerticalAlignment="Center" TabIndex="30">
    2. <TextBox.Text>
    3. <Binding x:Name="bin_amount" Path="amount" Mode="OneWayToSource" UpdateSourceTrigger="PropertyChanged">
    4. <Binding.ValidationRules>
    5. <local:buchung_valrules/>
    6. </Binding.ValidationRules>
    7. </Binding>
    8. </TextBox.Text>
    9. </TextBox>


    Hier noch die eingebundenen Ressourcen:

    XML-Quellcode

    1. <Window.Resources>
    2. <ResourceDictionary>
    3. <ResourceDictionary.MergedDictionaries>
    4. <ResourceDictionary Source="/slider_dict.xaml"/>
    5. </ResourceDictionary.MergedDictionaries>
    6. <local:ds_buchungen x:Key="Ds_buchungen"/>
    7. <CollectionViewSource x:Key="Tbl_transactionsViewSource" Source="{Binding tbl_transactions, Source={StaticResource Ds_buchungen}}"/>
    8. <CollectionViewSource x:Key="Tbl_konto_v01ViewSource2" Source="{Binding tbl_konto_v01, Source={StaticResource Ds_buchungen}}"/>
    9. <CollectionViewSource x:Key="aktive_konten" Source="{Binding tbl_konto_v01, Source={StaticResource Ds_buchungen}}"/>
    10. <CollectionViewSource x:Key="aktive_empfaenger" Source="{Binding tbl_receiver, Source={StaticResource Ds_buchungen}}"/>
    11. </ResourceDictionary>
    12. </Window.Resources>


    Meine Validierungsrule:

    VB.NET-Quellcode

    1. Imports System.Collections.Generic
    2. Imports System.Globalization
    3. Imports System.Linq
    4. Imports System.Text
    5. Imports System.Windows.Controls
    6. Public Class buchung_valrules
    7. Inherits ValidationRule
    8. Public Overloads Overrides Function Validate(value As Object, cultureInfo As CultureInfo) As ValidationResult
    9. 'Betrag darf nicht leer und negativ sein:
    10. Dim v_betrag As Decimal
    11. If Decimal.TryParse(value.ToString(), v_betrag) Then
    12. If v_betrag < 0 Then
    13. Return New ValidationResult(False, "Betrag darf nicht negativ sein")
    14. Else
    15. Return ValidationResult.ValidResult
    16. End If
    17. Else
    18. Return New ValidationResult(False, "Kein oder fehlender Betrag")
    19. End If
    20. Return ValidationResult.ValidResult
    21. End Function
    22. End Class


    Es passiert nun folgendes:
    Programm startet => Form öffnen => es erfolgt sofort der zugriff auf die Validationrule Klasse und das Textfeld wird rot umrahmt da es ja beim init leer ist.
    Gebe ich jetzt allerdings eine korrekte zahl ein in diesem Fall z.b. 1000 und gehe aus dem Feld wird nicht nochmal validiert.

    Ich habe versucht im "LostFocus" Event die Validierung anzustoßen:

    VB.NET-Quellcode

    1. Private Sub AmountTextBox_LostFocus(sender As Object, e As RoutedEventArgs) Handles AmountTextBox.LostFocus
    2. 'Validierung anstoßen
    3. AmountTextBox.GetBindingExpression(TextBox.TextProperty).UpdateSource()
    4. End Sub


    Das funktioniert aber auch nicht vielleicht kann mir jemand einen Hinweis geben was ich falsch mache.
    danke!
    mfG.
    Stephan
    Wpf und Dataset vertragen sich nicht gut.

    Ich würde dir sehr empfehlen, mit einfacheren "Versuchs-Aufbauten" dich dem Thema anzunähern.

    Versuch zB erstmal ein normales Viewmodel zu erstellen, ohne Datenbank, und sieh zu, dass du da deine ValidationRules richtig eingesetzt bekommst.

    Viewmodel ist dir ein Begriff? Weil sonst müssteste noch weiter zurück zu den Grundlagen gehen.

    Auch sieht mir dein Binding ühaupt nicht aus, als könne es funktionieren. Ist bei Wpf ziemlich blöd, dass man da keine richtigen Fehlermeldungen bekommt, sondern nur eine Laufzeit-Debug-Ausgabe ins Output-Window - haste da mal geguckt?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Hallo und danke für die Antwort.

    Das verstehe ich nicht ganz warum sich WPF und Dataset nicht vertragen sollen es gibt sogar von MS ein eigenes Tut wo die Bindung beschrieben wird, ok im Sinne des MVVM ist es wahrscheinlich nicht ganz sauber oder?
    Ich hab relativ viele Bücher zu Rate gezogen und die Validationrules in meinen anderen Beispielen funktionieren das traurige ist das kein einziges Buch in meinem Besitz auch nur Ansatzweise auf das Thema Datenbindung eingeht ohne ein Datagridview zu nutzen....

    Ich habe jetzt den Fehler eingrenzen können es ist folgendes Problem da die Form sowohl zum hinzufügen als auch zum editieren von Datensätzen geplant ist habe ich folgendes gemacht:

    VB.NET-Quellcode

    1. If v_editmode = True Then 'Editieren und einen Datensatz anzeigen
    2. Ds_buchungentbl_transactionsTableAdapter.Fill(Ds_buchungen.tbl_transactions)
    3. Tbl_transactionsViewSource = CType(Me.FindResource("Tbl_transactionsViewSource"), System.Windows.Data.CollectionViewSource)
    4. Tbl_transactionsViewSource.View.MoveCurrentToFirst()
    5. End If


    Da mir beim öffnen der Form immer der erste Datensatz (ich hab den Zeiger auch dorthin gestellt da ich noch keine bessere Lösung hatte) angezeigt wird habe ich mit einer Variable die Viewsource defacto weggeschalten, sobald ich das aber mache funktioniert die Validierung nicht, irgendwo hier muss also der "Hund" begraben sein.
    also das Problem ist somit:
    Erstelle ich keine ViewSource => keine Validierung aber Benutzer kann Daten eingeben und wenn notwendig speichern
    Erstelle ich eine Viewsource => Validierung funktioniert aber der Benutzer bekommt beim anlegen einen Datensatz angezeigt was ja nicht Sinn der Sache ist kann ich das irgendwie "unterdrücken"?

    Auch habe ich noch ein Problem in meiner Validierung bei der Eingabe ins Feld lässt er zwar "." eingeben was als falsch markiert ist das richtige "," wird aber nicht angenommen siehe meine erweiterte Klasse:

    VB.NET-Quellcode

    1. Public Overloads Overrides Function Validate(value As Object, cultureInfo As CultureInfo) As ValidationResult
    2. 'Betrag darf nicht leer und negativ sein:
    3. Dim v_betrag As Decimal
    4. Dim v_numstyle As NumberStyles = NumberStyles.AllowDecimalPoint Or NumberStyles.AllowThousands
    5. Dim v_cultur As CultureInfo = cultureInfo.CreateSpecificCulture("de-de")
    6. Debug.Print("Kultur: " & v_cultur.ToString)
    7. Debug.Print("Ausgangswert: " & value.ToString)
    8. If Decimal.TryParse(value.ToString, NumberStyles.AllowDecimalPoint, v_cultur, v_betrag) Then
    9. Debug.Print("betrag: " & v_betrag.ToString)
    10. If v_betrag < 0 Then
    11. Return New ValidationResult(False, "Betrag darf nicht negativ sein")
    12. Else
    13. Debug.Print("ok")
    14. Return ValidationResult.ValidResult
    15. End If
    16. Else
    17. Debug.Print("fehler im konvert " & v_betrag.ToString)
    18. Return New ValidationResult(False, "Kein oder fehlender Betrag")
    19. End If
    20. End Function

    Lustigerweise darf ich . eingeben was aber zu einem falschen ergebnis führt, das "," lässt er nicht zu und ändert mir eine Eingabe: 123,45 in 12345...
    mfG.
    Stephan

    kaifreeman schrieb:

    Das verstehe ich nicht ganz warum sich WPF und Dataset nicht vertragen sollen...
    Hattemer gestern grad: DataSet in WPF

    Also ordentliche Typen werden vom XamlEditor unterstützt, die DataRowViews leider nicht.
    Xaml-Cracks pfeifen oft auf diese Unterstützung, aber das andere Problem, dass man typDataRows in Styles und Templates garnet als Datentyp angeben kann - tja... :(
    Oft kennen die pfeifenden Xaml-Cracks auch garnet, worauf sie pfeifen, also wirf mal Blick rein:
    MVVM: "Binding-Picking" im Xaml-Editor
    So sollte findich alles Binding zu setzen sein - geht leider nicht immer, was ich eiglich skandalös finde (weil das konnte olle WinFoms schon besser, und das dolle neue Wpf fabriziert da lauter Fails).
    egal

    kaifreeman schrieb:

    ... es gibt sogar von MS ein eigenes Tut wo die Bindung beschrieben wird, ok im Sinne des MVVM ist es wahrscheinlich nicht ganz sauber oder?
    Ich kenn das Tut nu nicht, aber MSDNs CodeSamples sind öfter mal nicht ganz sauber :thumbdown:



    kaifreeman schrieb:

    da die Form sowohl zum hinzufügen als auch zum editieren von Datensätzen geplant ist habe ich folgendes gemacht...
    Findich ziemlich böse, eine Tabelle oder noch mehr abzurufen, nur um einen Datensatz zuzufügen.
    Dabei sind deine Daten doch längst da, das wird normalerweise nix gutes, wenn man dieselben Daten in derselben Anwendung mehrmals abruft, und die fahren dann da in doppelter Ausführung herum.
    Ma ganz abgesehen vonne performance.

    Überleg dir da am besten was anneres - das ist nix gutt, dass dein Dialog - ist ja wohl einer - ein eigenes Dataset enthält.
    Ich behaupte immer das Highlander-Prinzip: "Es darf nur ein Datenmodell geben in einer Anwendung, sonst ClusterFuck."

    ah - guggemol MVVM-Anwendungs-Struktur
    Vom Prinzip her könntest du so auch dein Dataset verfügbar machen, ohne das Highlander-Prinzip zu verletzen.
    So langsam verstehe ich das Problem ich verwende MVC Systematik bei PHP (z.b. beim PIP Framework) nachdem ich bisher nur Windows Forms genutzt habe war es nicht notwendig auf MVVM zuzugehen.

    Ich habe mir dein Beispiel angesehen mit der MVVM Struktur das ist soweit klar ich drücke mal einfach ganz simpel aus wie ich glaube das ich meine Anwendung basteln könnte:

    Klassen die die einzelnen Elemente repräsentieren z.b. Konten, Folder, Kategorien und die Buchungen selbst.
    Die Klassenelemente dienen als Ressource und könnten dann bei den einzelnen Forms an die Steuerelemente gebunden werden so das auch die Validierung bzw. das ganze Datenhandling innerhalb der Klasse passiert.
    Die Klassenelemente übergebe ich dann schlicht und ergreifend an das Dataset und in weiterer Folge an die DB.
    Wäre das eine gangbare Alternative? Anscheinend ist es ja nicht möglich ohne eine Bindung zu validieren womit mein Ansatz das Dataset zu binden obsolet ist.
    mfG.
    Stephan
    Erscheint mir komisch, nu eigene Klassen zu entwickeln, die dann an Dataset-Klassen zu übergeben, und die dann an die Datenbank.

    Normal nimmt man EntityFramework, wenn man mit Wpf auf Datenbanken los will.
    Das ist auch viel toller als die doofen alten Datasetse, nur bei mir zickt EF immer rum, zB beim Thema Löschweitergabe verknüpfter Datensätze.
    Aber guck dir mal meine Versuche damit an: EntityFramework-CodeFirst-Sample

    Ach - und das Thema Dialoge in Wpf ist auch sowas daher.
    Hier im Post wird auf CodeProjekt verlinkt, wie "mans" richtig macht: mycsharp.de/wbb2/thread.php?postid=3782785#post3782785
    Und auch sonst gehts da über Dialoge in Wpf.
    Jdfs wenn du dir das CP-Teil dann antust, kann sein, kriegst'n Vogel, was die da für einen Aufriss machen.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ ()

    So also ich habe den ganzen Tag damit zugebracht die komplette Anwendung neu zu schreiben und mit ins EntityFramework reinzubeißen.

    Es hat sich damit mein Problem mit der Validierung gelöst auch funktioniert das hinzufügen von Datensätzen mittlerweile sehr gut und ich habe die Anwendung jetzt auf Basis des MVVM Modells umgebaut.

    Danke für deine Hilfe schaut aus als ob ich jetzt zumindest wieder ein Stück weiterkommen werde.
    mfG.
    Stephan