Contact US

Log In

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips Forums!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!

*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.

Students Click Here

Class reference in a Form

Class reference in a Form

Class reference in a Form

Hello colleagues:

I have this class (container), named paxmarit:

Then in the second field (txtVrPgto1) of the class, in Procedure (Event): LostFocus, I have:

CODE -->

IF cboModoPgto1="CR - Cartão de Crédito"
    txtVrParcCC1 = txtVrPgto1

I put this class in a Form.

When I run the Form, I got this error:

cboModoPgto1 is the first field.

Do I need to use the class name (paxmarit) in the Form?

Thank you,

RE: Class reference in a Form

If a combobox control named cboXYZ is directly on a form - and important - directly on a form, you would refer to it with THISFORM.cbXYZ
If it's in a container on a form, you can adress it as THISFORM.containername.cboXYZ.

You see the pattern? You never address a contorl just by its name. That will make VFP think you mean a variable of that name, not a control.

Withiun a class, you don't have THISFORM available as the root and using THISFORM.containername in the class code would imply you later can only name the container by a specific name, also the container will maybe not end up on the form, but in a page of a pageframe on the form. So there is another mode of adressing a control rooting in THIS, which will depend on where your code is.

Intellisnse will help you with that, you can find the control a bit like you can find a directory going up with .. from a base directory to a higher level.

So if you have a combobox cboXYZ and a textbox txtABC that are side by side in a container class, you can write


If THIS.Parent.cboXYZ.value = "CR - Cartão de Crédito"
    THIS.Parent.txtVrParcCC1.Value = This.Value

Notice the importance of the keyword "THIS", it always refers to the control that has the code you write, so if you write code into an event of the container, THIS is the container, in the click of a button, THIS is the button.

Try it out interactively, don't just copy &paste this code example. If you open up the LostFocus event of the txtVrPgto1 control in the code editor and write just THIS.PARENT that would make you address the container the textbox is in and when you then write another dot, an intellisense dropdown list lists all the elements including txtVrPgto1, so all elements that are also in the container. You can even reach outside the container, if you already know you'll always put the container class on a page, you can get the page caption from This.Parent.Parent.Caption or, if you program in an event or method of the container THIS isw the container and THIS.PARENT is the page.

It's recommended you always program with such relative object names as the relative postions more often is stable, but there are other strategies to actually not need to address controls themselves at all, address the tables records and fields you use for data displayed in the controls. That's what I recommended just today in Mandy_crw's current thread.

If you write code that sets a value of a control you write code that acts as if it was a user seeing and using the form. Think about it, if a txtVrParcCC1 textbox has a controlsource like VrParc.CC1 then to change the value of the textbox you only need to change the value of the CC1 field. Your code has one advantage to a user only seeing and being able to use the form controls, it has all your programmer knowledge "behind the scenes" of what tables and fields you bind to controls. So make use of that knowledge,, set the table field to a new value, not the textbox.value, let the textbox.controlsource update the value.

So above code could be much shorter:


If sometable.somefield = "CR - Cartão de Crédito"
    REPLACE VrParc.CC1 WITH  This.Value

That's assuming txtVrParcCC1 is having a field CC1 of a remote view you call VrParc as its controlsource. I can't deduce what your combobox is bound to, maybe you just hardcode a list of values with AddItem(), but if you also use a controlsource/rowsource for it, selecting an item means setting the record pointer to that record and instead of getting the value from the control you can directly read from that current record.

Your code is able to act on the data directly without using the controls. The controls are the interface a user needs to interact, not your code. Anything you want to show to a user usually comes from a record of a table and you can always use that, there are cases where storing a value to a field would be indirection, for example if you want to show a message in a messagebox, a messagebox is not a control with a controlsource, but usually it is more direct to act on a DBF or cursor or view with code than acting on controls. If you make that your rule of thumb, you'll less often address controls at all and that also frees you from moving controls, arranging them differently, without the need to adapt code to those layout changes.


RE: Class reference in a Form

Oh, Chris, I have never used Parent... so Parent is for the next level (a container)!

I made the changes following your teaching and my form, with the class inside it, works as expected.

Thank you,

RE: Class reference in a Form

Quote (SitesMasstec)

so Parent is for the next level (a container)!
Yes, it depends of course.

If you design a button in a container, put that container on a page of a pageframe on a form, then program in the button click
THIS is the button
THIS.PARENT is the container
In the latter cases it may make more sense to address from the other direction. If you need to access the form, THISFORM of course always works. If you know there's only one pageframe on the form, it's perhaps better to address it as THISFORM.PAGEFRAME1. There's no equivalent of THISCLASS that makes you access whatever is the root level of the class, no matter how deep a control is buried in the structure.

This mehtod of addressing has its poros and cons. I know from other languages also based on WinForm you can address controls just by their name as you tried first, but then no two controls are allowed to have the same name. And that is a good rule, but makes it hard to add several of the same containers to a form, even. So no solution is ideal for all cases.

You could add a property oClass to every control and in the init of any class you could use THIS.SetAll('oClass',THIS) and then no matter whether a control is directly on the level of a class, or in another container or page, it would be possible to address the class level element, i.e. the container by THIS.oClass. It's a bit cheating, but it can make addressing other things easier. The ideal way to not need anything like that is to address data, though, not controls, neither siblings, children or parents.


Red Flag This Post

Please let us know here why this post is inappropriate. Reasons such as off-topic, duplicates, flames, illegal, vulgar, or students posting their homework.

Red Flag Submitted

Thank you for helping keep Tek-Tips Forums free from inappropriate posts.
The Tek-Tips staff will check this out and take appropriate action.

Reply To This Thread

Posting in the Tek-Tips forums is a member-only feature.

Click Here to join Tek-Tips and talk with other members! Already a Member? Login

Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close