You'll learn more about record scoping in RecordBuffers and Record Scope. It's helpful to cover all the syntax forms that can affect it before discussing the meaning of record scope in different situations. For now, you can scope or associate records in one or more tables with a DO block by using the FOR phrase:
DO FOR record[, record] . . .
Each record names a record you want to work with in the block and scopes it to the block. References within that block to fields the record contains are automatically associated with that record.
You have already seen an example of frame scoping in the code in the enable_UI procedure of h-CustOrderWin2.w and in the button triggers you created based on that code:
DISPLAY Customer.CustNum Customer.Name Customer.Address Customer.City
Customer.State
WITH FRAME CustQuery IN WINDOW CustWin.
You can use the phrase WITH FRAME frame-name and, optionally, IN WINDOW window-name to identify which frame you're talking about when you display fields or take other actions on objects in frames. If you wish, you can scope all the statements in a DO block with a frame by appending the WITH FRAME phrase to the DO statement itself.
For example, here's the BtnNext trigger block again with the frame qualifier moved to the DO statement:
DO:
GET NEXT CustQuery.
IF AVAILABLE Customer THEN
DO WITH FRAME CustQuery: DISPLAY Customer.CustNum Customer.Name Customer.Address Customer.City
Customer.State.
{&OPEN-BROWSERS-IN-QUERY-CustQuery}
END.
END.
Whether you name the frame in individual statements or in the block header, this makes sure that the AVM understands that you want the fields displayed in the frame where you defined them. If you don't do this, then depending on the context, the AVM might display the fields in a different frame.
To see the result of not explicitly defining a frame scope:
1. Edit the WITH FRAME phrase out of the BtnNext trigger altogether, so it looks like this:
DO:
GET NEXT CustQuery.
IF AVAILABLE Customer THEN
DO /* WITH FRAME CustQuery */: DISPLAY Customer.CustNum Customer.Name Customer.Address
Customer.City Customer.State.
{&OPEN-BROWSERS-IN-QUERY-CustQuery}
END.
END.
2. Run the window and click the Next button:
What happened here? Since the DISPLAY statement wasn't qualified with any indication of where to display the fields, the AVM created a brand new frame, laid out the fields in it, and displayed it on top of the other frame in your window. To keep this from happening, make sure that all statements that deal with frames are always clear about where actions should take place. The AppBuilder, Progress Developer Studio for OpenEdge, and the other tools take care of this for you most of the time, but when you add code of your own to procedures, you might need to qualify it with the frame name. Otherwise, the AVM displays objects in the frame that is scoped to the nearest enclosing block that defines a frame. If there is no explicit frame definition, then you get the result you just saw here. the AVM displays the data in an unnamed default frame. Except in the simplest test procedures, like the procedures this book uses to demonstrate the looping syntax, you never want to use the default frame in your applications.
There are other phrases you can use to qualify a DO block, but they mostly deal with transactions and error handling, which is described in ManagingTransactions.