Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

BINDEVENT(loForm, "Destroy", ThisForm, "grid_setup") datasession problem 1

Status
Not open for further replies.

DrAlbany

Programmer
Jun 14, 2003
46
0
0
GB
Hi All..,

Hope someone can shed some light onto a little problem i'm having.

I read an article about using BINDEVENT instead of setting a form to modal so that when the "edit" form is release you can refresh the parent form's grid with any edited / new values.

Configuration:-
Windows 7 Pro
Visual foxpro 9 SP2

I am using private data sessions for all of the forms.

I have a parent form with a grid, when you double click on a grid row the "edit form" is launched.

Here is the code on the parent form.
***************************************
DO FORM forms\table_custom_add_edit NAME loForm WITH lnID && lnID is the ID of the record to be edited

BINDEVENT(loForm, "Destroy", ThisForm, "grid_setup")

loForm.SHOW
***************************************
I then edit the values, save and close the form.

In the "edit" form the "destroy" event has a simple "a = 1" otherwise I found that the Destroy event was not being triggered, which caused the BINDEVENT() not to trigger.

My problem seems to be that when the Destroy even is triggered, the edit form is not release but the "grid_setup" event is being triggered in the parent form... but the datasession seems to be that of the "edit" form and not the parent form, so I get a "table not found" error when the "grid_setup" is being triggered.

I have tried adding code to the "grid_setup" to check the data session and change it to the forms data session, but that seems to be causing other problems.

Any Ideas why this may be happening and any ideas on how to fix it.

Thanks for your time.

Regards

Steve


If you alway do what you've always done, you always get what you've always got.
 
I'm not clear why you need to use BINDEVENTS().

Your aim is to launch a modal form that lets the user edit a value. When you close that form, you want the grid in the launching form to reflect the edited value. Is that correct?

If so, there are easier ways of doing it. You could have the editing form update the table that you used to populate the grid. Then, after the launching form has opened the editing form, you can have it refresh the grid. If you are using physical tables rather than cursors, that should work. The fact that they are in different data sessions won't matter.

Alternatively, you could return the updated value from the editing form via a variable. To do that, place a RETURN command in the form's Unload method. In the calling form, add a TO clause to the DO FORM command; this clause specifies the variable that will receive the updated value. You can then update the underlying cursor or table with that value, and either refresh or set focus to the grid.

If I have misunderstood the question, my apologies.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Mike, the idea is to use BindEvent instead of a modal form, not additionally.

And the other form doesn't need a form reference passed in and any other mechanism, you simply react to the detroy event of the form you call.

The idea is good. Would you refer the article, maybe it already has the answer. You should read about the nFlags parameter. You'll want to let the Destroy event finish first, before your grid_setup routine runs, so you'll have to use nFlag=1, which is not the default.

Your code located in the main form shouldn't have the need to witch back to the main form data session. And all you would need to do is a Thisform.Refresh(), which should be done anyway.
If you would need to get access to anything in the edit form, then Destroy is too late. You should only need to refresh yourself to get the updated data, which I suppose the grid_setup method does.

Bye, Olaf.
 
As an alternative, you can access form's properties.

Code:
PUBLIC ofrm,loform
ofrm = CREATEOBJECT("MyForm")
ofrm.show()

DEFINE CLASS myform as Form && main form
	DataSession = 2
	ADD OBJECT grd as grid WITH columncount = 2,recordsource='cc'
	PROCEDURE load
		CREATE CURSOR cc (id I AUTOINC,cc C(10) DEFAULT SYS(2015))
		APPEND BLANK 
		APPEND BLANK 
		GO TOP 
	ENDPROC
	PROCEDURE init
		This.grd.column2.removeobject("text1")
		This.grd.column2.addobject("text1","mytext")
		This.grd.column2.text1.visible=.t.
	ENDPROC
	PROCEDURE grid_setup
		LOCAL lclc
*		MESSAGEBOX(VARTYPE(loForm)) && X => the variable is null because the form is released
		lclc = _screen.Forms(1).cc && but the form object is still in the _screen's form collection
		SELECT cc
		replace cc WITH m.lclc
	ENDPROC
ENDDEFINE

DEFINE CLASS mytext as TextBox && the textbox inside the grid, with the dblclick event
	margin = 0
	borderstyle = 0
	PROCEDURE dblclick
		SELECT cc
		lnid = id
*		DO FORM f2 NAME loForm WITH lnID && lnID is the ID of the record to be edited
		loForm = CREATEOBJECT("my2form")
		UNBINDEVENTS(loForm, "Destroy",ThisForm, "grid_setup")
		BINDEVENT(loForm, "Destroy", ThisForm, "grid_setup")
		loForm.SHOW
	ENDPROC
ENDDEFINE

DEFINE CLASS my2form as Form && edit form
*	DataSession = 1
	Id = 0
	cc = ''
	ADD OBJECT Text1 as Textbox WITH ControlSource = "ThisForm.cc",selectonentry = .T. && form property instead of a table
	ADD OBJECT cmd as commandbutton WITH caption = "close",top = 50
	PROCEDURE init
		LPARAMETERS lnId
		This.id = m.lnId
		This.text1.Value = cc.cc
	ENDPROC
	PROCEDURE destroy
		*
	ENDPROC
	PROCEDURE cmd.click
		ThisForm.Release
	ENDPROC
ENDDEFINE

Respectfully,
Vilhelm-Ion Praisach
Resita, Romania
 
Hi Mike..,

Thanks for you reply... I don't want to use a modal form. The program I am creating is quite complex in data editing wise, so I want the user to be able to use other parts of the system if need be i.e. answer the phone and deal with a query then come back to the edit form.

Vilhelm-Ion..,

Many thanks.. I will have a play.

The article was: [URL unfurl="true"]http://www.rcs-solutions.com/blog/CategoryView,category,VFP.aspx[/url]

If you alway do what you've always done, you always get what you've always got.
 
Thanks Olaf..,

I think yours may be the answer I'm looking for.

Regards

Steve





If you alway do what you've always done, you always get what you've always got.
 
Hmmm...

Still not working...

In the parent form I'm using a sql select to a cursor...

and when the "grid_setup" is triggered from the "destroy" event the cursor is being created in the "edit" windows data session.

Very strange...

Baffling me...

If you alway do what you've always done, you always get what you've always got.
 
I don't want to use a modal form. The program I am creating is quite complex in data editing wise, so I want the user to be able to use other parts of the system if need be i.e. answer the phone and deal with a query then come back to the edit form.

Makes perfect sense.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Got it working... [wipes sweat from brow]

In the "grid_refresh" I have added
************************************************
IF SET("DATASESSION") != THIS.DataSessionId
SET DATASESSION TO THIS.DataSessionId
ENDIF
************************************************

and in the parent edit windows I have changed to:-
*******************************************************
LPARAMETERS lnid

DO FORM forms\table_custom_add_edit NAME loForm WITH lnid

BINDEVENT(loForm, "Destroy", ThisForm, "grid_setup",5)

*loForm.SHOW
*********************************************************

Removed the loForm.Show - no longer needed with adding nFlag = 5 to the BINDEVENT (1 + 4)


Seems to be working.

Many thanks for your input guys... it got me thinking and experimenting with it again after pulling my hair out all of yesterday :)

Regards

Steve

If you alway do what you've always done, you always get what you've always got.
 
grid_refresh" = "grid_setup"

Same thing, but I referenced it as "grid_setup"

If you alway do what you've always done, you always get what you've always got.
 
Closing a window is of course involving Windows Messages, but the nFlags bit 2 (value 4) only is needed, when you bind to windows messages, not if you bind to VFP events.

And in the normal case the code executing in a form with a certain datasessionid would only create cursors in that datasession.

Let's see how bindevent plays a role.
Code:
oSession1=CreateObject("mysession")
? oSession1.DataSessionID

oSession2=CreateObject("mysession")
? oSession2.DataSessionID

BindEvent(oSession2,"createalias",oSession1,"createaliasbound",1)
oSession2.createalias()

set
Set Step On 
* now inspect the datasessions and their aliases

Define Class mySession as Session
   Procedure createalias()
       Create Cursor ("cursor_in_sessionid"+Transform(this.DataSessionId)) (id I)
   EndProc
          
   Procedure createaliasbound()
       Create Cursor ("bindevent_cursor_in_sessionid"+Transform(this.DataSessionId)) (id I)
   EndProc
EndDefine

Both cursors are create in oSession2, even though oSession1 is triggered by the event. The bindevent_cursor has the suffix of the other datasessionid, as the code is run in oSession1, yet the cursor is created in oSesssion2.

So yes, bindevents work as you experienced.

What works to decouple this is making use of RAISEVENT:

Code:
oSession1=CreateObject("mysession")
? oSession1.DataSessionID

oSession2=CreateObject("mysession")
? oSession2.DataSessionID

BindEvent(oSession2,"createalias",oSession1,"createaliasbound",1)
oSession2.createalias()

set
Set Step On 
* now inspect the datasessions and their aliases

Define Class mySession as Session
   Procedure createalias()
       Create Cursor ("cursor_in_sessionid"+Transform(this.DataSessionId)) (id I)
   EndProc
          
   Procedure createaliasbound()
       RaiseEvent(This,"createalias")
       *Create Cursor ("bindevent_cursor_in_sessionid"+Transform(this.DataSessionId)) (id I)
   EndProc
EndDefine

Now each data session has one cursor created.

To apply that to your situation, don't bind to grid_setup, bind to a new method "childformexit" (however you call it is up to you) and in that caallbackevent RAISEEVENT(This,"grid_setup"). It's cleaner than SETting DATASESSION.

Bye, Olaf.
 
DrAlbany

Hello, my english not good... :) But I use google translator..... ;)

Code:
DO FORM forms\table_custom_add_edit NAME loForm WITH lnID && lnID is the ID of the record to be edited

BINDEVENT(loForm, "Destroy", ThisForm, "grid_setup")

loForm.SHOW

Your code is correct.

Reading your post, if you use what you did in the first post, will work, just need to put the * of the form Destroy and it will shoot method..

example

Code:
Destroy
*

Explanation: To run the VFP need to fire the form's Destroy, and it does not need code, just need to put the asterisk (*) there.

I´m sure my english, but I hope you have understood. :)
 
lardecristo.

that was never the problem, instead of * DrAlbany put "a=1" in the Destroy event.

Bye, Olaf.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top