Validate, schon wieder ... [Erledigt]

Grafische Primitive, XbaseParts und Darstellungsfragen allgemein.

Moderator: Moderatoren

Antworten
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14655
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 88 Mal
Kontaktdaten:

Validate, schon wieder ... [Erledigt]

Beitrag von Jan »

Ich habe folgenden Code:

Code: Alles auswählen

... 
oSleGegeben := XbpSle():new(oRahmenWechselgeld, , {120, 30}, {200, 35}, {{XBP_PP_FGCLR, GRA_CLR_BLUE}})
oSleGegeben:validate := {|oSle| vergleicheWerte(oSle, nGesamtSumme)}
oSleGegeben:setInputFocus := {|x, y, obj| obj:setColorBG(GRA_CLR_YELLOW), ;
                                          MEMVAR->goFokus := obj, ;
                                          oStaticInfo:SetCaption("Bitte den Gegeben-Betrag eingeben")}
oSleGegeben:create()
...


FUNCTION vergleicheWerte(o, nGesamtSumme)

LOCAL lRueckgabe := .T.
LOCAL n := Val(o:editBuffer)

IF Int(n * 100) < Int(nGesamtSumme * 100)
   lRueckgabe := .F.
ENDIF

RETURN lRueckgabe
Alle soweit einverstanden damit? Aber warum zum Henker wird die Funktion vergleicheWerte() NIEMALS durchlaufen?

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12909
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 46 Mal

Re: Validate, schon wieder ...

Beitrag von AUGE_OHR »

Jan hat geschrieben:Alle soweit einverstanden damit? Aber warum zum Henker wird die Funktion vergleicheWerte() NIEMALS durchlaufen?
also wenn es wirklich der ganze Code ist : Wo ist dein o:datalink ?
gruss by OHR
Jimmy
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14655
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 88 Mal
Kontaktdaten:

Re: Validate, schon wieder ...

Beitrag von Jan »

Jimmy,

da gibt es keinen. Aber selbst wenn: Das ändert nichts an der Tatsache, das die Funktion nicht durchlaufen wird.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15697
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Validate, schon wieder ...

Beitrag von brandelh »

Hallo Jan,

diese Instanzvariable kommt von der DataRef Klasse, möglicherweise wird diese erst beim Speichern also GETDATA() geprüft.
Eventuell aber auch nur wenn ein Datalink vorhanden ist ... das würde erklären warum ich die nicht verwendet und sogar vergessen habe :D
Gruß
Hubert
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14655
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 88 Mal
Kontaktdaten:

Re: Validate, schon wieder ...

Beitrag von Jan »

Hubert,

nein, am Datalink kann das nicht liegen, denn das ändert nichts.

Und :getData() dürfte es auch nicht sein, denn es wird in der Onlinehilfe explizit darauf hingewiesen, das man in der Funktion selber nur :editBuffer() nutzen darf, um den :getData() nicht auszulösen. Denn das hätte ja den Nachteil, das dann der :killInputFocus() abgearbeitet würde mit allem, was dazu gehört. Was ja aber bei einer Rückgabe von .F. von :validate definitiv nicht geschehen darf.

Oder verstehe ich das falsch?

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15697
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Validate, schon wieder ...

Beitrag von brandelh »

Hallo Jan,

wenn getData() intern nicht benutzt werden darf, da sonst gespeichert wird, dann kann es auch nicht davor nötig sein, da stimme ich dir zu,
war auch nur ein Gedanke ... aber getData() verursacht definitiv keinen Focus-Wechsel solange nicht eine MsgBox() oder ähnliches aufgerufen wird.

Vielleicht ist das ja fehlerhaft, gibt es eventuell einen PDR ?

GANZ WICHTIG an der Aussage des Hilfetextes !!!

Wenn ich nur den Inhalt des SLE wissen will, sollte ich immer :editBuffer() statt :getData() nutzen :D
Gruß
Hubert
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12909
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 46 Mal

Re: Validate, schon wieder ...

Beitrag von AUGE_OHR »

Jan hat geschrieben:

Code: Alles auswählen

... 
oSleGegeben := XbpSle():new(oRahmenWechselgeld, , {120, 30}, {200, 35}, {{XBP_PP_FGCLR, GRA_CLR_BLUE}})
oSleGegeben:validate := {|oSle| vergleicheWerte(oSle, nGesamtSumme)}
oSleGegeben:setInputFocus := {|x, y, obj| obj:setColorBG(GRA_CLR_YELLOW), ;
                                          MEMVAR->goFokus := obj, ;
                                          oStaticInfo:SetCaption("Bitte den Gegeben-Betrag eingeben")}
oSleGegeben:create()
weil du nirgendwo das o:validate() ausführst :!:

Code: Alles auswählen

METHOD NewForm:SetValid()

   ::Name   :validate := { |oSelf| ::IsValid(oSelf,1) }
   ::Nummer :validate := { |oSelf| ::IsValid(oSelf,2) }
   ::Datum  :validate := { |oSelf| ::IsValid(oSelf,3) }
   ::Logic  :validate := { |oSelf| ::IsValid(oSelf,4) }

   ::Name   :killInputFocus := {| u1, u2, oSelf | oSelf:validate() }
   ::Nummer :killInputFocus := {| u1, u2, oSelf | oSelf:validate() }
   ::Datum  :killInputFocus := {| u1, u2, oSelf | oSelf:validate() }
   ::Logic  :killInputFocus := {| u1, u2, oSelf | oSelf:validate() }


oder gleich so

   ::Name   :killInputFocus := {| u1, u2, oSelf | ::IsValid(oSelf,1) }
   ::Nummer :killInputFocus := {| u1, u2, oSelf | ::IsValid(oSelf,2) }
   ::Datum  :killInputFocus := {| u1, u2, oSelf | ::IsValid(oSelf,3) }
   ::Logic  :killInputFocus := {| u1, u2, oSelf | ::IsValid(oSelf,4) }

RETURN self

METHOD NewForm:IsValid(oSelf,nNo)
LOCAL lRet := .T.

   DO CASE
      CASE nNo = 1
         IF EMPTY(TRIM(oSelf:editbuffer()))
            Msgbox("Name darf nicht leer sein")
            lRet := .F.
         ENDIF
      CASE nNo = 2
         IF EMPTY(TRIM(oSelf:editbuffer()))
            Msgbox("Nummer darf nicht leer sein")
            lRet := .F.
         ELSEIF VAL(oSelf:editbuffer()) = 0
            Msgbox("Wert Nummer = 0")
            lRet := .F.
         ENDIF
...
   ENDCASE

   IF lRet = .F.
      // Wert erneut lesen
      oSelf:setData()

      // wenn leer wäre das hierbei "fatal"

      // zurück auf das SLE
      SetAppFocus(oSelf)
   ENDIF

RETURN lRet
gruss by OHR
Jimmy
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15697
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Validate, schon wieder ...

Beitrag von brandelh »

Hi,

mit o:validate() hat Jimmy natürlich vollkommen recht, aber ...

Code: Alles auswählen

::Name   :killInputFocus := {| u1, u2, oSelf | IF(::IsValid(oSelf,1),::Tudies(1),NIL) }
::Nummer :killInputFocus := {| u1, u2, oSelf | IF(::IsValid(oSelf,2),::Tudies(2),NIL) }
::Datum  :killInputFocus := {| u1, u2, oSelf | IF(::IsValid(oSelf,3),::Tudies(3),NIL) }
::Logic  :killInputFocus := {| u1, u2, oSelf | IF(::IsValid(oSelf,4),::Tudies(4),NIL) }
das ist ein potentieller Kandidat für eine Endlosschleife, da muss man höllisch aufpassen !

Warum ...
Vorgabe:
Name und Nummer dürfen nicht leer sein und der Name darf noch nicht vorkommen.
Beide SLE sind beim Anfang leer, weil man ja was eigeben soll.
Der Kunde gibt einen Namen ein, der schon verwendet wurde und verlässt das Feld.

Was passiert:
Killinputfocus prüft valid(), während es schon im neuen Feld (Nummer) steht.
Es will den Fehler melden z.b. msgbox() ... damit wird auch Nummer verlassen und ...
auch dort wird valid() ausgeführt und die nächste Fehlermeldung will kommen,
wahrscheinlich muss diese aber warten, da die erste msgbox schneller ist.
Jede der Fehlerbehandlungsroutinen setzt den Focus ins eigene Feld und schon
gibt es die nächste Fehlermeldung ...

Mit solchen Schleifen habe ich bis zur Verzweiflung gekämpft, bevor ich umgestiegen bin auf:
1. Abgeleitete SLE die einfache Plausis prüfen können (z.B. J / N Eingaben => Meine Datum etc. Controls in der Wissensbasis
2. Seitenvalidierung, erst wenn ich "Speichern" drücke validiere ich den Inhalt aller Felder in einer Methode !
Diese meldet alle Probleme (färbt dabei auch die SLE ein) und setzt den Focus ins erste Problemfeld.
3. Wenn ich wirklich in KillInputfocus was benötige (z.B. enable()/disable() nach SLE Feldinhalt), rufe ich dort eine Methode auf,
die sich um alle solchen Sachen auf der Seite kümmert und auch andere SLE in Betracht ziehen kann.
Keinesfalls dürfen zwei SLE mit dieser Regelung in der TAB Reihenfolge hintereinander stehen ohne dass der zweite Aufruf
erkennen kann, dass gerade der erste noch in Bearbeitung ist ...
Gruß
Hubert
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16517
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Re: Validate, schon wieder ...

Beitrag von Martin Altmann »

Moin Hubert,
brandelh hat geschrieben:Keinesfalls dürfen zwei SLE mit dieser Regelung in der TAB Reihenfolge hintereinander stehen ohne dass der zweite Aufruf erkennen kann, dass gerade der erste noch in Bearbeitung ist ...
wenig hinzuzufügen - ausser dass diese Einschränkung Unsinn ist 8).
Die brauchen nicht Mal hintereinander stehen, um Probleme zu bereiten - denke an die Maus! Ich kann in einem der beiden SLEs stehen und in das andere klicken.

Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14655
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 88 Mal
Kontaktdaten:

Re: Validate, schon wieder ...

Beitrag von Jan »

Mooooment mal. Jimmy: Bislang habe ich Dein Beispiel noch nicht umgesetzt. Denn das würde nichts nützen sonlange die aufgerufene Funktion überhaupt nicht angesprungen wird. DAS ist ja jetzt erstmal das Problem.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15697
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Validate, schon wieder ...

Beitrag von brandelh »

Hallo Jan,

du hättest oben besser lesen sollen ;-)

in :validate => iVar wird zwar der Codeblock hinterlegt, der zur Prüfung ausgeführt werden soll (meist einmalig),
aber automatisch wird gar nix aufgerufen ! Das war mein und dein Gedankenfehler.

Du selbsts oder wie in Jimmys Beispiel im anderen Thread must die Methode :validate() aufrufen um diesen Codeblock auszuführen !

Aber bevor zu zu sehr jubelst, solltest du auch mein dortiges Beispiel der Nebenwirkungen ansehen ;-)
:arrow: http://www.xbaseforum.de/viewtopic.php? ... 1&start=50
Gruß
Hubert
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14655
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 88 Mal
Kontaktdaten:

Re: Validate, schon wieder ...

Beitrag von Jan »

Ja aber hallo. Warum ist das eigentlich so kompliziert? Warum muß man ein :validate einbauen, wenn das dann doch so nicht funktioniert, sondern man das später noch einmal aufrufen muß? Gibt es dafür eine logische Erklärung? Warum wird das in der Onlinehilfe nicht sauber dokumentiert?

Aber OK, so klappt das jetzt auch.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15697
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Validate, schon wieder ...

Beitrag von brandelh »

Hallo Jan,

:validate := {|| } ... legt einmal fest, wie genau die Eingabe dieses Controls validiert werden soll, wenn es denn soweit ist !

das kennen wir doch von :killInputFocus, :keyBoard, und all den anderen CallBack-Slots.
Bei diesen wird irgendwann ein Ereignis ausgelöst z.B. Tastendruck oder Mausklick, und genau dann wird die dazu gehörige Methode ausgeführt.
Eine VALIDATE() auslösende Aktion gibt es aber in Windows nicht, man kann ja nicht einfach automatisch wegen Focusverlust oder Tastendruck eine Validierung erzwingen.
Xbase++ kann gar nicht wissen ob und wann du validieren willst, und wie meine Beispiele zeigen ist damit auch schnell eine Endlosschleife produziert ...

Daher musst du in deinem Code selbst die Validierung auslösen, die Trennung erlaubt dir aber dann mit den Arrays zu arbeiten ...

Code: Alles auswählen

aEval( ::aEditControls, {|oXbp| iif(oXbp:validate(), speichern, ignorieren) } ) 
eine solche Schleifenverarbeitung wäre nicht möglich, wenn nicht oben schon der CodeBlock belegt worden wäre.
Ob ein Feld als solches überhaupt allene wissen kann ob es valide ist, darüber haben wir ja schon gesprochen.

Hier übrigens mein Beispiel (Jimmy abgewandeltes), das genau zeigt was wann ausgelöst wird und in welcher Reihenfolge ...
ein KeyBoard() Slot löscht hier nach Eingabe von "Fehler" im "Namen" das nächste Feld Nummer um dort einen Fehler zu provozieren,
dann will er zurück, da der Name "Fehler" nicht erlaubt ist. Im MLE oben sieht man die Reihenfolge der Protokollaufrufe ... und dass das KeyBoard SetAppFocus() nicht gegen den
Validate aus dem 2. Feld ankommt :!: :!: :!: was ich schon immer sage ... PS: NEU führt immer noch zur Endlosschleife, aber CTRL+C bricht das Programm ab :D
DEMO_SLE_HB2.zip
(7.89 KiB) 129-mal heruntergeladen
PS: und natürlich geht die Validierung im Keyboard-Slot auch nicht, wenn man mit der Maus springt ;-)
Gruß
Hubert
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14655
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 88 Mal
Kontaktdaten:

Re: Validate, schon wieder ...

Beitrag von Jan »

Hubert,

tja, und ich hatte vorausgesetzt, das wenn ich den :validate-Slot belege, der bei jedem denkbaren Ereignis automatisch ausgeführt wird. Das ich mich darum also nicht mehr kümmern muß. Daher mein Unverständnis.

So kann man sich irren.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15697
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Validate, schon wieder ...

Beitrag von brandelh »

Hi,

Wenn man es unbedingt so machen will, müsste die Methode die die Validierung prüft selbst zunächst prüfen, wer aktuell den Focus hat.
Eventuell man selbst (=kein Problem) oder ein anderes Xbp ?
Wenn ein anderes das hätte, könnte man prüfen ob dieses SetAppFocus():Validate() wäre => kein Problem, wir können machen was wir wollen, mit SetAppFocus(oXbp) den Focus zurücksetzen.
(was passiert eigentlich wenn man oXbp:Valid() aufruft, und :validate auf NIL sitzt ? Ich hoffe ein .t. als Antwort ;-) )
Wenn es aber nicht valide wäre, müsste man z.b. mit einem static in der Funktion/Methode den nächsten Aufruf blockieren !
Danach erst mit SetAppFocus(oXbp) den Focus zurücksetzen.

Das sollte funktionieren.
Gruß
Hubert
Antworten