Seite 1 von 1

XbpBrowse synchronisieren [Erledigt]

Verfasst: Mi, 06. Dez 2017 12:21
von Jan
Hallo,

irgendwie stecke ich da gerade fest.

Ich habe einen Browse, der mir ausgewählte Felder einer dbf anzeigt. Dadrüber zeige ich mir Daten aus dem aktuellen Satz in @...SAY an - die Daten werden aus der dbf genommen, nicht aus dem Browse. Alles wunderschön synchron. Skippe ich durch den Browse per Cursor-Tasten, wird immer der aktuelle Satz im Browse als Grundlage für die Anzeige dadrüber genommen, alles passt.

Aber: Unter bestimmten Bedingungen muß ich z. B. nach einem Wechsel auf den nächsten Satz diesen automatisch überspringen. Ich drücke also PfeilAb, und statt in die nächste Zeile zu gehen, soll der in die übernächste gehen. Und natürlich dabei Anzeige, Browse, und den Satz in der dbf dabei schön synchron halten.

Und da steh ich wie Ochs vorm Berge. irgendwas übersehe ich da offenbar. Denn ich bekomme das nicht hin. Mir driften dabei die dbf und der Browse offenbar irgendwie auseinander. Hat jemand einen Tipp für mich, wie ich das hinbekommen kann?

Jan

Re: XbpBrowse synchronisieren

Verfasst: Mi, 06. Dez 2017 12:58
von Tom
Du kannst die Navi-Codeblöcke entsprechend bestücken (SkipBlock) oder, simpler, direkt ein weiteres oBrowse:Down() auslösen, wenn Du irgendwie merkst, dass der Datensatz übersprungen werden muss. Wenn Deine SAYs auf ItemMarked reagieren, wovon ich ausgehe, müsste das gut funktionieren.

Re: XbpBrowse synchronisieren

Verfasst: Mi, 06. Dez 2017 13:06
von brandelh
@ JAN,

wie machst du das mit dem Überspringen und werden die übersprungenen Sätze auch im Browser angezeigt ?
Wie sieht der Code aus, der die Daten refreshed ?

Re: XbpBrowse synchronisieren

Verfasst: Mi, 06. Dez 2017 13:14
von Tom
Gute Frage(n). Ich würde das, wie angemerkt, ans Browse hängen, wobei die Synchronisation über ItemMarked ausgelöst wird, das ist verlässlich. Das Browse setzt ja den Tabellenzeiger, also müsste sonst nichts weiter abgeglichen werden. Der Datensatz, der im Browse hervorgehoben wird, muss angezeigt werden, fertig. Sprünge kann man in der Logik auslösen. Wichtig ist nur, dass man z.B. XbpBrowse:Down() auch ein ForceStable() folgen lässt, sonst steht der Zeiger nicht richtig.

Re: XbpBrowse synchronisieren

Verfasst: Mi, 06. Dez 2017 13:23
von brandelh
Hallo Tom,

ich meinte JAN, ohne Code ... viel raten ;-)

du warst dann nur schneller beim schreiben. Ich denke auch, dass ItemMarked() erst aufgerufen wird, wenn die Zeile stabil angezeigt wird.
Ich hatte zunächst an :stableblock gedacht. Ich dachte die down() Methoden des browsers lösen ein forcestable aus, daher hätte ich die genommen um weiter zu springen,
oder eben im skip block, wenn die übersprungenen Zeilen gar nicht angezeigt werden sollen.
Wenn man in der Datei selbst was ändert, muss man eventuell RefreshAll() ausführen, das verschiebt aber wohl den Cursor ... ist schon lange her dass ich XbpBrowse() genutzt habe.

Re: XbpBrowse synchronisieren

Verfasst: Mi, 06. Dez 2017 14:16
von Jan
Hallo,

Ihr ward viel zu schnell mit euren Ideen ... :-D Genial .... Ich hatte nur gerade noch einen externen Entwickler am Hörer, konnte nicht genau so schnell reagieren.

Also: Das mit :down() und nachfolgendem :forceStable() hatte ich auch versucht. Hatte aber nicht geklappt. Auch nicht mit :refreshall(). Man versucht alles alles, wenn es nicht klappen will.

Wenn ich einfach so blättere, dann klappt das ja alles. Der Browse refreshed, die Daten in den SAY werden korrekt angezeigt. Aber sobald ich programmgesteuert blättere, kommt der aus dem Tritt.

Ein :itemMarked habe ich übrigens nicht drin.

Ich denke aber gerade daran das der sich eventuell irgendwo selber einholt. Denn dieses programmgesteuerte skippen passiert in einer udf, die sowohl von :keyboard als auch von :stableBlock aufgerufen wird. Der würde also in seiner eigenen UDF sich selber noch mal aufrufen durch den :stableBlock. Oder sehe ich das eventuell falsch?

Jan

Re: XbpBrowse synchronisieren

Verfasst: Mi, 06. Dez 2017 14:32
von brandelh
code code code ;-)

Wie ruft der keyboard() und der StableBlock() die UDF auf (code)
Wie sieht die UDF aus ... (code)

danach können wir mit dem Raten anfangen, welcher Event wie wo wann ausgelöst wird.
Wenn die UDF direkt auf die DBF geht, dann ist browser und datendatei nicht mehr syncron, ein refreshall() wird fällig, dieses müsste eine Stabilisierung auslösen, ich denke viele unnötige Refreshes ...

Noch eine Frage, wird der "übersprungene" Satz im Browser angezeigt oder soll der nicht angezeigt werden ?

Re: XbpBrowse synchronisieren

Verfasst: Mi, 06. Dez 2017 14:57
von Jan
Hubert,

drängel, drängel, drängel... So kenn ich Dich ja gar nicht.

Das mit dem Code ist etwas kompliziert. Die UDF ist nämlich 530 Zeilen lang. Ich kann aber mal versuchen, das Wesentliche daraus zu extrahieren.

Für etwas mehr Verständnis, was ich machen möchte: Ich habe eine Anwendung mit OEM-Oberfläche. Da habe ich einen XbpBrowse rein gebaut, weil der mir anzeigetechnisch ein paar Möglichkeiten eröffnet, die der vorher verwendete DbEdit() nicht hat.

Hier geht es darum, Adressdubletten zu finden. Der Dialog teilt sich in drei Teile: Die gesamte untere Hälfte ist der Browse. Die obere Hälfte ist nochmal geteilt, so das ich hier zwei viertel Dialogbereiche habe: Links steht die auf Dubletten zu überprüfende Adresse. Rechts davon die mögliche Dublette.

Die UDF, die sowohl von :keyboard als auch :stableblock aufgerufen wird, füllt die beiden oberen Bereiche mit den gefundenen Daten. Wobei in der UDF nach einem von meinem Kunden vorgegebenen Algorithmus die nächste Adresse gesucht wird, die für die linke Adresse eine Dublette sein könnte. Wird eine gefunden, wird diese im Browse markiert und rechts angezeigt. Der Benutzer sieht dann links die zu prüfende Adresse, rechts die mögliche Dublette, und kann durch Tastendruck entscheiden, ob das nun eine ist oder nicht.

Es kann dabei auch sein, das die gefundene Adresse keine Dublette ist, aber die nächste, die im Browse angezeigte. Dann kann der Benutzer mit den Cursortasten dahin gehen und diese Paarung als Dublette markieren.

Soweit klappt das auch alles ganz gut.

Es gibt dabei aber ein Problem: Wenn der Benutzer mit den Cursortasten im Browse blättert, und dann auf die Adresse kommt, die schon oben links angezeigt wird (= Adressnummer stimmt überein), dann ist das nicht eine Dublette, sondern die exakt gleiche Adresse. Sowas möchte ich auf jeden Fall vermeiden. Und in dem Fall direkt auf den nächsten Satz runter springen. Und hier habe ich das Problem. Mache ich in der Überprüfung, ob die beiden Adressnummern die gleiche sind, ein :down(), dann gerät das ganze Konstrukt irgendwie aus dem Tritt.

Ich habe z. B. gerade mal diese Überprüfung, ob die beiden Adressnummern übereinstimmen, in den Codeblock VOR den :keyboard-UDF-Aufruf gelegt. Denn das passiert ja nur, wenn ich etwas mit der Tastatur gemacht habe, und der :forceStable sollte danach automatisch kommen. Resultat: Rechts oben wird die korrekte übernächste Adresse angezeigt. Im Browse aber nur die nächste, identische. Und bei weiteren Cursorbewegungen geht gar nichts mehr - klar, der weiß ja nicht mehr wo der steht. Browse und Satzzeiger der dbf passen nicht mehr zusammen.

Jan

Re: XbpBrowse synchronisieren

Verfasst: Mi, 06. Dez 2017 15:15
von Martin Altmann
Warum bietest Du die ausgewählte (Master-)Adresse überhaupt noch in der Dublettenmasse an?
Lass die da weg und Du hast kein (Logik)Problem mehr.

Viele Grüße,
Martin

Re: XbpBrowse synchronisieren

Verfasst: Mi, 06. Dez 2017 15:22
von Jan
Hallo Martin,

ansich eine gute Idee. Aber dann müsste ich auf die Adress-Datenbank einen Filter legen auf Adressnummer <> gerade zu prüfende Adresse. Ich befürchte mal, das wird bei knapp 1/2 Mio. Adressen über das Netzwerk ein wenig langsam werden.

Jan

Re: XbpBrowse synchronisieren

Verfasst: Mi, 06. Dez 2017 15:34
von Jan
Oh man, ich könnt mir so in den Hintern beißen (wenn das denn orthopädisch irgendwie ginge)! :angry4:

Also, erstmal habe ich den Tipp von oben aufgegriffen und die Überprüfung auf die exakte Adressenübereinstimmung in die Codeblocks gestellt. Das hat schon mal was gebracht.

Aber dann: Das Problem kam danach ganz woanders her. Aus der Dublettenkontrolle meines Kunden. Da war nach etwas Mergen verschiedener Bestandteile ein Passus drin, der immer wieder automatisch auf einen ganz anderen Satz gesprungen ist. Was dann natürlich alles andere ausgehebelt hat, was ich da umgeschrieben hatte.

Ich hab das jetzt erstmal so geregelt das ich nachschaue, auf welcher Zeile im Browse ich gerade stehe. Der muß bei den automatischen möglichen Treffern immer in Zeile 1 stehen. Steht der woanders, dann muß das ein manuelles Skippen gewesen sein, und dann überspringe ich das.

Wie gut das ich gleich erstmal zum Sport fahre. Jetzt muß ich mich ein klein wenig abreagieren ...

danke für Eure Ideen zu dem Punkt, die ja letztendlich auf den korrekten Weg geführt haben.

Jan

Re: XbpBrowse synchronisieren

Verfasst: Mi, 06. Dez 2017 16:04
von brandelh
Die Beschreibung ist gut verständlich :!:

Ich vermute, dass der skipblock so aussieht:

:skipBlock meistens {|n| DbSkipper(n) }

man könnte dort natürlich prüfen, ob die ID gleich der anderen ist und weiter springen, aber
- eventuell würde die Zeile nicht mehr angezeigt, oder
- was passiert wenn n = 1 übergeben aber n=2 zurückgegeben wird, also mehr Sätze geskipped werden wie angefordert. Ich weiß es nicht, daher besser im stableblock oder wie TOM meinte im itemMarked slot !

Nennen wir mal die Prüf-Funktion SkipOverActiveRecord() und gehen davon aus, dass du wie beschrieben die vor dem Anzeigerefresh im Keyboard und stableblock ausführst ...
Im Keyboard ist es auf jeden Fall falsch, dort löschen, im Stable erst am Ende des Codeblocks prüfen und ausführen:

Code: Alles auswählen

:keyboard := {|| JansSayUpdate() }
:stableblock := {|| JansSayUpdate(); SkipOverActiveRecord( oBrowser, nActiveID, nSelectBereichDBF ) } // falls der Rückgabewert von JansSayUpdate() wichtig ist, muss man das anders schachteln

function SkipOverActiveRecord( oBrowser, nActiveID, nSelectBereichDBF )
   if nActiveID = (nSelectBereichDBF)->nRecID // bei Strings == verwenden
      oBrowser:down() // KEIN REFRESH der DBF, denn die Zeile war und bleibt stable
      oBrowser:forceStable() // laut Hilfe --> lIsStable braucht man hier eine Schleife oder geht das immer ok ????
   endif
return nil
wenn es bei Stable nicht geht, dann die Funktion in itemMarked einsetzen, wie TOM vorgeschlagen hat.

PS: oh da waren einige schneller