Seite 1 von 1

dataLink im XbpBrowse

Verfasst: Di, 12. Apr 2016 16:07
von Wonderer
Hallo,

ich arbeite an einem Formular in dem links ein XbpBrowse 2Spalten aus einer temp.Tabelle enthält (STATUS + Name) und rechts daneben ist das Eingabe-Formular mit den SLEs, Checkbox, Dropdown u.ä. Für das Abspeichern der Werte habe ich mich jetzt nach Startschwierigkeiten dafür entschieden auf das EVENT xbeBRW_ItemMarked zu reagieren. Dadurch musste ich mir die vorherige Position in der DB und im XbpBrowse merken - diese setzen -> Werte aus Formular in den Datensatz speichern - und wieder zurück zu Datensatz/Zeile der nach ItemMarked gesetzt war.

Code: Alles auswählen

	oPart := oDlg:childFromName( FORM_BROWSE_MOD )
	
	SELECT 260
	nRecVor := RecNo()	
	nRowVor := oPart:rowPos
	
	DbGoto( nRecNo )
	oPart:rowPos := nRowNo
	
	DbRLock()
		REPLACE AKTIV WITH bAktiv
		REPLACE MODELL WITH cName
	DbCommit()
	oBrs:refreshCurrent()
	oBrs:deHilite()
	
	DbGoto( nRecVor )
	
	oBrs:rowPos := nRowVor
	oBrs:refreshCurrent()
	oBrs:hilite()
Das funktioniert auch. Jetzt dachte ich mir das müsste doch eigentlich auch über den DataLink zu bewerkstelligen sein den man dem AddColumn mitgibt?

folgendes habe ich jetzt versucht aber das funktioniert nicht:

Code: Alles auswählen

oBrs:addColumn( { |x| IIf( x==nil, AKTIV, AKTIV:=SetAppWindow():childFromName( FORM_MOD_CHECK_AKTIV ):getData() ) }, , aKopf[1] )
oBrs:addColumn( { |x| IIf( x==nil, rtrim(MODELL), MODELL:=SetAppWindow():childFromName( FORM_MOD_EDIT_NAME ):getData() ) }, , aKopf[2] )
Ich vermute mal ich habe noch nicht richtig verstanden wann das SetData diesen Codeblock aufruft?
Wenn eine andere Zeile angeklickt wird im XbpBrowse - dachte ich mir - soll vorm Wechsel die vorherige Zeile die Daten aus den Formular-Feldern nehmen und in die DB-Tabelle zurückschreiben..

danke wieder mal für eure Hilfe... :)

Re: dataLink im XbpBrowse

Verfasst: Di, 12. Apr 2016 22:02
von AUGE_OHR
Wonderer hat geschrieben:auf das EVENT xbeBRW_ItemMarked zu reagieren.
wenn du GUI verwendest dann solltest du dein Cl*pper "Denken" umstellen ;-)

der xbeBRW_ItemMarked Event wird bei jeder Bewegung gesendet/ausgeführt aber für die "Auswahl" ist der

Code: Alles auswählen

  oBrowse:itemSelected := {| uNIL1, uNIL2, self | ::MyEdit() } 	
zuständig.

links für das XbpBrowse hast du mit

Code: Alles auswählen

   oBrowse:addColumn() 
XbpColumn-Objekte erzeugt und an das Browse angehängt.
der enthalte Codeblock bezieht sich auf die entsprechende Column.
das du nun, im GET Teil, auf ein XbPart verweist was ein o:GetData() ausführen soll ist "ungewöhnlich" :shock: ... (s.h. ::MySave() )

solange du in einem Browse "navigierst" sollte nichts weiter passieren ... bis zum o:stable ( TBrowse ) bzw. o:stableBlock ( XbpBrowse() )
im o:stableBlock Codeblock würde man nun das rechte Fenster mit den SLE "refresh"(en) mit

Code: Alles auswählen

   * Werte in Editcontrols übertragen
   AEval ( ::EditControls, { | oXbp | oXbp:SetData() } )
   ::nRecno := FIELD->RECNO()
nun kann der User im Formular was eingeben/ändern und das soll nun abgespeichert werden.
unter GUI hat man dafür nun einen Button ... weil dieser einen Codeblock Slot hat !

Code: Alles auswählen

   oPbSave:activate := {| uNIL1, uNIL2, self | IF(::MySave(), lExit := .T., lExit := ::ErrorSave() ) }

Inline Methode MySave()
LOCAL lRet := .F.
   GOTO (::nRecno)
   IF RLOCK() // wegen Netzwerk
      // VOR dem o:GetData() wenn es sich um FIELDs handelt !
      AEval ( ::EditControls, { | oXbp | oXbp:GetData() } )
      // wenn Variabel verwende wurden
      // REPLACE FIELD->XYZ WITH cBlabla
      UNLOCK       
      // GOTO (::nRecno)         
   
      ::oBrowse:RefreshCurrent() 
      SetAppFocus(::oBrowse)
      lRet := .T.
   ELSE
      // Error feststellen    
   ENDIF
RETURN lRet
nun könnte der User mit der Maus aber auf das Browse clicken ... ohne "save" [-X ... wenn nicht MODAL.

unter GUI wäre es auch möglich das der User einen Satz im Browse auswählt -> Thread neues "Fenster" :-"
das Fenster könnte im o:Close Callback Slot nun auch die ::MySave() Anweisung enthalten

Code: Alles auswählen

   oDialog:Close := { || IF(::MySave(), lExit := .T., lExit := ::MyErrorSave() ) }
aber viele Wege führen nach Rom ... OOP ist einer der Wege.

Re: dataLink im XbpBrowse

Verfasst: Mi, 13. Apr 2016 11:45
von Wonderer
AUGE_OHR hat geschrieben:wenn du GUI verwendest dann solltest du dein Cl*pper "Denken" umstellen ;-)
Ich glaube ich habe noch keine festgefahrenes Denken bzgl. Clipper/XBase. Die wenigen Zeilen Code in den letzten Jahren in der Sprache sind so wenig gefestigt, dass ich ziemlich häufig in der Referenz nachschauen muss wie denn jetzt die Parameter richtig wären :)
der xbeBRW_ItemMarked Event wird bei jeder Bewegung gesendet/ausgeführt aber für die "Auswahl" ist <snip...>
Danke, aber ich möchte das Übertragen der Werte anhand der ID im XbpBrowse bei 1-fachem Klick auf eine Zeile auslösen - nicht mit Doppelklick oder ENTER.
das du nun, im GET Teil, auf ein XbPart verweist was ein o:GetData() ausführen soll ist "ungewöhnlich" :shock:
Das vermutete ich auch dass das 'merkwürdig' ist. :D
solange du in einem Browse "navigierst" sollte nichts weiter passieren ... bis zum o:stable ( TBrowse ) bzw. o:stableBlock ( XbpBrowse() )
im o:stableBlock Codeblock würde man nun das rechte Fenster mit den SLE "refresh"(en) mit <snip...>
Ok, danke - das schaue ich mir mal an.
nun kann der User im Formular was eingeben/ändern und das soll nun abgespeichert werden.
unter GUI hat man dafür nun einen Button ... weil dieser einen Codeblock Slot hat !
Das ist jetzt natürlich eine Design-Frage bzgl. Nutzerfreundlichkeit. Ganz am Anfang dachte ich auch ich nehme einen Button zum Speichern.
Jetzt habe ich mich aber entschieden in dem Moment zu speichern in dem der Nutzer dieses EDIT-Aktionsformular verlässt bzw. einen andern DS auswählt.
nun könnte der User mit der Maus aber auf das Browse clicken ... ohne "save"
Daher sind meine Aufrufe in der Event-Schleife in der Art:

Code: Alles auswählen

 if nEvent == xbeBRW_ItemMarked

 	oBrs:refreshCurrent()

	cName := (260)->NAME

	if cName != cNameZuvor

	 oPart := SetAppWindow():childFromName( FORM_SELECT_MOD_AKTION )

 	 if oPart:getItem(oPart:getData()[1])=="Bearbeiten"
	 	PspeicherDaten( rtrim(cNameZuvor), oDlg, nRecNo, nRowNo )
	 	PfuelleEditFormular( rtrim(cName), @aDaten, oDlg )
	 endif
  	 cNameZuvor := cName
	endif

 	SELECT 260
	nRecNo	:= RecNo()
	nRowNo  := oBrs:rowPos
Dazu kommt dann später noch das überprüfen ob überhaupt was geändert wurde und evtl.eine ConfirmBox (deswegen Verwendung von @aDaten )
unter GUI wäre es auch möglich das der User einen Satz im Browse auswählt -> Thread neues "Fenster" :-"
das Fenster könnte im o:Close Callback Slot nun auch die ::MySave() Anweisung enthalten
Danke, ich habe mich gegen dieses Konzept entschieden - ich hoffe das bringt mich nicht an Grenzen. :)
aber viele Wege führen nach Rom ... OOP ist einer der Wege.
es ist besser nochmal Weg/Ziele abzugleichen bevor man dann sagen kann: "Ziel erfasst - ENERGIE!"

SCNR - der Feierabend besteht bei mir zur Zeit aus StarTrek auf TELE5.. :D

Re: dataLink im XbpBrowse

Verfasst: Mi, 13. Apr 2016 12:14
von Jan
Wonderer hat geschrieben:SCNR - der Feierabend besteht bei mir zur Zeit aus StarTrek auf TELE5.. :D
Das guck ich an Bürotagen WÄHREND des Programmierens. Oder schieb mir statt dessen die BlueRay rein - die habe ich nämlich von allen Staffeln der relevanten Unterserien (Nicht DS9, die finde ich blöd, aber alle anderen ST-Universen). Es lebe der regelmäßige Geburtstag/Weihnachten und eine Familie, die einem dann sowas schenkt :-D

Jan

Re: dataLink im XbpBrowse

Verfasst: Mi, 13. Apr 2016 17:58
von Tom
Es lebe der regelmäßige Geburtstag/Weihnachten und eine Familie, die einem dann sowas schenkt
Ähem. Oder Amazon Prime, da sind alle Star-Trek-Serien kostenlos enthalten, zum Teil sogar in Full HD.

Re: dataLink im XbpBrowse

Verfasst: Mi, 13. Apr 2016 19:37
von AUGE_OHR
Wonderer hat geschrieben:
der xbeBRW_ItemMarked Event wird bei jeder Bewegung gesendet/ausgeführt aber für die "Auswahl" ist <snip...>
Danke, aber ich möchte das Übertragen der Werte anhand der ID im XbpBrowse bei 1-fachem Klick auf eine Zeile auslösen - nicht mit Doppelklick oder ENTER.
"was" willst du im Browse denn auslösen ?

im Browse "navigierst" du und wartest bis er "Stable" ist. im o:StableBlock kommt dann das "refresh"(en) der SLE.

in deinem Fall benötigst du IMHO dann keinen weiteren Codeblock Slot da die "Position" ja schon stimmt.
eine "Bewegung" in der selben DBF (Workarea), nachdem sie "Stable" ist, sollte man nicht machen !

der "Save" Button ist auf der rechten Seite bei den SLE womit du "bestätigst" das die Änderungen in die DBF geschrieben werden sollen.

Re: dataLink im XbpBrowse

Verfasst: Do, 14. Apr 2016 7:30
von Wonderer
Im Prinzip hätte ich gern auf ein Event reagiert das vor dem Wechsel der selektierten Zeile auftritt und dann danach auf eines welches danach getriggert wird (das dann wie du schreibst StableBlock ist) - so wie es in einigen ähnlichen Anwendungs-Fällen auch im DotNet funktioniert. Da aber ItemMarked erst danach auftritt muss ich zum Aktualisieren wieder zurück zum vorherigen Datensatz - speichern - und wieder dahin wo der User mit seiner Aktion im Browse wollte. Mir gefällt das auch nicht so richtig und eine Schaltfläche zum Speichern ist sicher eine bessere Alternative zu diesem Konzept. Zumindest funktioniert das jetzt aber hier so mit dem Workaround dass ich manuell RowPos setze und die HiLite-Methoden aufrufe.

Re: dataLink im XbpBrowse

Verfasst: Do, 14. Apr 2016 8:26
von AUGE_OHR
Wonderer hat geschrieben:Da aber ItemMarked erst danach auftritt muss ich zum Aktualisieren wieder zurück zum vorherigen Datensatz - speichern - und wieder dahin wo der User mit seiner Aktion im Browse wollte.
genau das verstehe ich nicht was du damit meinst ? :dontknow:

du kannst entweder im XbpBrowse oder in einem SLE sein :boxing: nur ein Xbpart hat den Focus.
wenn du im SLE bist bewegt*** sich nichts im XbpBrowse ... auch nicht wenn du es verlässt.
***evtl bei Wheel < Win 10

wenn du möchtest das er beim "verlassen" eines SLE "automatisch" was macht dann siehe dir den o:killInputFocus Callback Slot an.
den Callback Slot kannst du wie den von einem "Save" Button bestücken.

Code: Alles auswählen

oSLE:killInputFocus := {| uNIL1, uNIL2, oSelf | IF(SaveData(oSelf),oBrowse:RefreshCurrent(),ErrorLock(oSelf)) }

FUNCTION SaveData(oSelf) 
LOCAL lRet := .F.
LOCAL nRec := RECNO()
IF RLOCK()
   oSelf:GetData()
   UNLOCK
   GOTO(nRec) // statt COMMIT
   lRet := .T.
ENDIF
RETURN lRet
wenn .T. wird der Satz im Browser aktualisiert d.h. neu von Datenträger eingelesen.
ich sehen keinen Grund warum sich o:Rowpos oder o:Hilite ( wenn Focus) geändert haben sollte. [-X

eine Veränderung der Position in der DBF, nach einem "Stable" in der selben "Workspace", sollte man IMHO vermeiden.
unter Xbase++ kann man dafür Threads benutzen welche jede ihre eigene "Workspace( list() )" haben.

Re: dataLink im XbpBrowse

Verfasst: Fr, 15. Apr 2016 7:49
von Wonderer
Danke, das ist auf jeden Fall die viel bessere Variante wenn man keinen Button fürs Speichern haben möchte.
Und bei den den andern XbaseParts für Forumlare gibt es ebensolche Slots wie z.b. selected der Checkbox... :)

Re: dataLink im XbpBrowse

Verfasst: Fr, 15. Apr 2016 8:30
von Rolf Ramacher
Hallo und guten Morgen

vielleicht hilft dir das. hierbei klickst du mit doppelklick auf die entsprechende Zeile. es wird der ausgewählte Datensatz ermittelt und an Artikalauswahl weitergegeben.
nach der Rückkehr zu diesem Dialog erfolgt wieder ein Refresh
obrowse wird in diesem Fall nicht als Lokal Variable definiert.

Code: Alles auswählen

 		oBrowse:addColumn(FieldBlock(cField),nBreite,aSpalt[i],,) 
		oBrowse:itemSelected:={|| nSatz:=Eval(oBrowse:phyPosBlock),cArtnr:=ArtikelAuswahl(nSatz,oDlg,aFelder),;
							oBrowse:refreshall(),SetAppFocus(oBrowse),oSleSuche:clear(),;
							oSleSuche:dataLink := {|x| IIf( x==NIL, cArtnr, cArtnr := x ) },;							
							oSleSuche:setdata()} 

Re: dataLink im XbpBrowse

Verfasst: So, 17. Apr 2016 8:11
von AUGE_OHR
Jan hat geschrieben:
Wonderer hat geschrieben:SCNR - der Feierabend besteht bei mir zur Zeit aus StarTrek auf TELE5.. :D
Das guck ich an Bürotagen WÄHREND des Programmierens.
bei mir ist es Formel 1 (Shanghai)

Re: dataLink im XbpBrowse

Verfasst: Fr, 06. Mai 2016 14:45
von Wonderer
Danke Rolf, beim Design hatte ich mich dafür entschieden die Formular-Felder mit den Daten gleich rechts neben dem XbpBrowse zu haben damit nicht extra ein neues Fenster aufpoppt.

Auf jeden Fall bin ich nun am bitteren Ende angelangt mit meiner Idee beim ItemMarked den vorherigen Datensatz zu speichern.
Beim Klick auf den Scrollbalken führt mein Code zu ziemlich unvorhersagbaren Sprüngen weil ich ja erst
DbGoto ( nRec )
und dann
oBrs:rowPos := nPos

verwendete - rowPos ist aber lediglich die Nummer der sichtbaren Zeilen und je nach dem wo die Markierung relatiov vorher war verschiebt sich dann alles.

Lange Rede kurzer Sinn - ein XbpPushbutton [Speichern] wird eingebaut - wie langweilig einfach.. *lach* *hust*