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 Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

form vs component init order and parameter availability 1

Status
Not open for further replies.

steve4king

IS-IT--Management
Feb 6, 2007
154
US
Alrighty, this seems like a really newbish question, but it's got me stumped for the moment.

When a form is created/displayed using "do form with.."
The order is:

Form.load
Components.init
Form.init

Parameters passed during "do form _ with " are only accepted by the form's init process.
Since that occurs after the component's init process, those params are obviously not available during the component's init.

Just for better organization, and increased maintainability I prefer to keep each objects initialization in it's own init process..

So for this example, I have a grid that hides certain columns dynamically, based on one of these parameters.
To make this function correctly, I need to attach this hiding function to the form's init rather than the grid's init. (making the form's init larger and less easily maintained)

Is there a trick any of you use to get around this?

Thanks,
-Stephen
 
Well, one simple trick is of course to define public variables, but that's a bad alternative.

So let's talk about how to live with the fact. The reasoning behind this is to go the opposite approach and enable the one main form event to handle each control, as it's already there.

What's really the decision for the column hiding/showing? If it's user right, this should be known by the application object, where a user logs in. So each component that initializese depending on user rights should know how to verify them calling into either goApp or a user manager object, something global, but not just a global variable, a global manager. Dito for current language or other global settings. These should not be passed in to objects, but should be retrieved by them calling into the manager responsible for that.

Actually, if you'd want to make a control dependent on init parameters, it should be init parameters of the control, not of the form, shouldn't it be? But who creates the controls? That's a two stage process, in some manner you already init the control at design time by putting it to a form, on the other side the init event runs by the form being created, no matter if the form is inited by DO FORM or is a form class inited by CreateObject. The VFP base form class is creating and thereby initing all it's inner controls, somewhere after it's Load and it's Init, you don't have any hook or event you could change to pass in any parameters to the single control Inits. The base form inits all it's control without passing in anything, obviously.

As unfortunate as it is, designing controls to need init parameters is the first mistake, from the outset. To put code in the init of controls is not wrong, but it should be code actively knowing "who to ask" and getting it's values from somewhere instead of being told from outside by parameters. That's a bit like parameterizing a click event.

The only reasoning for init parameters of controls would be to create them at runtime programmatically. That's not a route I would go, that's shifting the paradigm of how you design, maintain and run forms. That paradigm also is lived and successful as a way to design web pages with HTML. I did a few years and then did winforms and even though there are nice dynamically working javascript frameworks and awesome principles of programming, I'd rather stay with the Wysiwyg form design at design time, if possible. There are of course HTML wysiwyg editors, too, but you know the principle, there are many OSes and many browsers.

So for your detail problem I'd go the route to initially have all columns invisible, which could end up invisible and either let the form init handle the column visibility (which is still before the form first shows anyway), or let the grid column do something like this.visible = goApp.oUsermanager.verifiyprivilege(xyz) or RETURN goApp.oUsermanager.verifiyprivilege(xyz) from init to suppress being created at all.

Another big help is the forms BindControl property. Put that .F. and only set it .T. in the form init, then you don't have any problems with grids binding to the wrong alias, just because the alias specified at design time does not yet exist when the grid inits.

Bye, Olaf.
 
Since the grid's configuration is dependent on values passed to the form, the grid can't set itself up until the form has set itself up.

Give the grid a method called "setup" (or whatever name pleases you) and call that method, passing the necessary parameters, from the form's init. This is just a basic organizing issue.

You'll never be able to decouple form from controls as long as controls are dependent on form parameters. You're actually creating an intentional dependency.
 
Or, put another way, call the grid's "hiding" function from within the form's Init. At that point, you know the parameter values, so you can either pass those as parameters to the hiding function, or store them in properties of the form, where they will be available to all the subsequent methods.

Keep in mind too that the grid (in fact, the entire form) will be invisible at this stage (it only becomes visible at the end of the Init), so you won't need to worry about the visual effect of the columns changing while the user is looking at it.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips, training, consultancy
 
Come to think of it, there's another approach you can take:

1. Store the parameter value in a property of the calling form. For the sake of example, let's call that property cValue.

2. In the Load event of the called form, add this code:

THISFORM.oCaller = _SCREEN.ActiveForm

where oCaller is a property of the called form. The effect will be to store an object reference to the calling form in oCaller. (This will work, because _SCREEN.ActiveForm does not change until after the Load).

3. Within the called form, you can now refer to oCaller.cValue to get the required value. This will be available while the controls are being initialised, so you can use it to hide your grid columns.

This approach comes into its own when you have a large number of values to pass in this way. But, most of the time, the solutions given earlier in this thread would be better.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips, training, consultancy
 
I'm patching pre-existing code. I normally am not a fan of chaining along parameters, esp those that are required by components.
But I don't want to change more code than I have to either.

Great information as always Olaf, thank you.

I like that idea Mike. That should work nicely. Thank you.
Keeps the organization of the form a little better, and reduces the dependency on parameters during init.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top