In an attempt to make an optiongroup handle a logical controlsource,
I made a custom option group class based on the standard
optiongroup class. It has the standard two option buttons.

The only customization is the addition of the following
access and assign methods for the Value property:

Value_Access:

WAIT window "Accessing: "+TRANSFORM(THIS.Value) TIMEOUT 1
RETURN IIF(THIS.Value = 1, .T., .F.)


Value_Assign:

wait window "Assigning: "+TRANSFORM(m.vNewVal) TIMEOUT 1
This.Value = IIF(m.vNewVal = .T., 1, 2)

The ControlSource of the optiongroup is set to a logical field
in a table:

theField
--------
T
F
T
F
T

When the form starts up the wait window with "Assigning .T."
is displayed about 4 times - apparently during the form's
paint and refresh methods.

Okay, that's the field value. So far so good.

Clicking a button that does a SKIP and a Form.Refresh() displays
"Assigning .F.", the optiongroup correctly updates to show the
second optionbutton selected, but then "Assigning .T." is shown
and the optiongroup switches back to the first button being
selected. Not good. As a result, as you skip through the
table, theField gets set to .T. as the record pointer hits each
record.

Any idea where this second assignment to .T. is coming from?
This seems very close to working and is a nice simple solution,
but this unexpected assignment is messing it up! Turning on
Event Tracking seems to indicate that the .T. assignment might
be happening when the form's Paint() method is envoked during the
form refresh.

Yes, I know that a checkbox can easily be used in this case,
but the interface calls for an optiongroup. I could change
the underlying table to a text field with "Y" and "N" values,
but leaving the field logical would be prefered for ease of
data processing.

-- TRW
_______________________________________
t i m . w i t o r t
_______________________________________

Re: Why won't this custom option group work? by Roger

Roger
Fri Jun 22 02:29:23 CDT 2007

Hi Tim,

I changed your Value_Assign method as follows:

LPARAMETERS vNewVal
If Vartype(vNewVal) = "L"
This.Value = Iif(vNewVal,1,2)
Else
This.Value = vNewVal
EndIf
Replace (JustExt(This.ControlSource)) ;
With Iif(This.Value = 1, .T.,.F.) ;
In (JustStem(This.ControlSource))

There may be a more elegant way but it worked!

-Roger


"Tim Witort" <tim_witort@hotmail.com> wrote in message
news:Xns99566B5ADCF01timwitortwrotethis@216.196.97.131...
> In an attempt to make an optiongroup handle a logical controlsource,
> I made a custom option group class based on the standard
> optiongroup class. It has the standard two option buttons.
>
> The only customization is the addition of the following
> access and assign methods for the Value property:
>
> Value_Access:
>
> WAIT window "Accessing: "+TRANSFORM(THIS.Value) TIMEOUT 1
> RETURN IIF(THIS.Value = 1, .T., .F.)
>
>
> Value_Assign:
>
> wait window "Assigning: "+TRANSFORM(m.vNewVal) TIMEOUT 1
> This.Value = IIF(m.vNewVal = .T., 1, 2)
>
> The ControlSource of the optiongroup is set to a logical field
> in a table:
>
> theField
> --------
> T
> F
> T
> F
> T
>
> When the form starts up the wait window with "Assigning .T."
> is displayed about 4 times - apparently during the form's
> paint and refresh methods.
>
> Okay, that's the field value. So far so good.
>
> Clicking a button that does a SKIP and a Form.Refresh() displays
> "Assigning .F.", the optiongroup correctly updates to show the
> second optionbutton selected, but then "Assigning .T." is shown
> and the optiongroup switches back to the first button being
> selected. Not good. As a result, as you skip through the
> table, theField gets set to .T. as the record pointer hits each
> record.
>
> Any idea where this second assignment to .T. is coming from?
> This seems very close to working and is a nice simple solution,
> but this unexpected assignment is messing it up! Turning on
> Event Tracking seems to indicate that the .T. assignment might
> be happening when the form's Paint() method is envoked during the
> form refresh.
>
> Yes, I know that a checkbox can easily be used in this case,
> but the interface calls for an optiongroup. I could change
> the underlying table to a text field with "Y" and "N" values,
> but leaving the field logical would be prefered for ease of
> data processing.
>
> -- TRW
> _______________________________________
> t i m . w i t o r t
> _______________________________________



Re: Why won't this custom option group work? by tim_witort

tim_witort
Fri Jun 22 12:16:51 CDT 2007

Roger Ansell seemed to utter in news:eMvHU6JtHHA.1168@TK2MSFTNGP02.phx.gbl:

> "Tim Witort" <tim_witort@hotmail.com> wrote in message
> news:Xns99566B5ADCF01timwitortwrotethis@216.196.97.131...
>> In an attempt to make an optiongroup handle a logical controlsource,
>> I made a custom option group class based on the standard
>> optiongroup class. It has the standard two option buttons.
>>
>> The only customization is the addition of the following
>> access and assign methods for the Value property:
>>
>> Value_Access:
>>
>> WAIT window "Accessing: "+TRANSFORM(THIS.Value) TIMEOUT 1
>> RETURN IIF(THIS.Value = 1, .T., .F.)
>>
>>
>> Value_Assign:
>>
>> wait window "Assigning: "+TRANSFORM(m.vNewVal) TIMEOUT 1
>> This.Value = IIF(m.vNewVal = .T., 1, 2)
>>
>> The ControlSource of the optiongroup is set to a logical field
>> in a table:
>>
>> theField
>> --------
>> T
>> F
>> T
>> F
>> T
>>
>> When the form starts up the wait window with "Assigning .T."
>> is displayed about 4 times - apparently during the form's
>> paint and refresh methods.
>>
>> Okay, that's the field value. So far so good.
>>
>> Clicking a button that does a SKIP and a Form.Refresh() displays
>> "Assigning .F.", the optiongroup correctly updates to show the
>> second optionbutton selected, but then "Assigning .T." is shown
>> and the optiongroup switches back to the first button being
>> selected. Not good. As a result, as you skip through the
>> table, theField gets set to .T. as the record pointer hits each
>> record.
>>
>> Any idea where this second assignment to .T. is coming from?
>> This seems very close to working and is a nice simple solution,
>> but this unexpected assignment is messing it up! Turning on
>> Event Tracking seems to indicate that the .T. assignment might
>> be happening when the form's Paint() method is envoked during the
>> form refresh.
>>
>> Yes, I know that a checkbox can easily be used in this case,
>> but the interface calls for an optiongroup. I could change
>> the underlying table to a text field with "Y" and "N" values,
>> but leaving the field logical would be prefered for ease of
>> data processing.

> Hi Tim,
>
> I changed your Value_Assign method as follows:
>
> LPARAMETERS vNewVal
> If Vartype(vNewVal) = "L"
> This.Value = Iif(vNewVal,1,2)
> Else
> This.Value = vNewVal
> EndIf
> Replace (JustExt(This.ControlSource)) ;
> With Iif(This.Value = 1, .T.,.F.) ;
> In (JustStem(This.ControlSource))
>
> There may be a more elegant way but it worked!
>
> -Roger
>

I'll have to try that! So it appears to be related to the
updating of the control source not working exactly how
expected, eh?

Thanks for the idea.

-- TRW
_______________________________________
t i m . w i t o r t
_______________________________________

Re: Why won't this custom option group work? by Roger

Roger
Fri Jun 22 12:41:52 CDT 2007


"Tim Witort" <tim_witort@hotmail.com> wrote:

> I'll have to try that! So it appears to be related to the
> updating of the control source not working exactly how
> expected, eh?

Yup. The problem is that the Value of the OptionGroup
must always be numeric, so there's no way that it can
update a Logical ControlSource without explicitly doing
a Replace in the Value_Assign method.

Funnily enough, a couple of years ago, I had the exact
reverse requirement ... a class based on a Container
object containing 2+ CheckBoxes with a common Integer
ControlSource. Of course, it couldn't use Access & Assign
methods, so I was curious about your approach.

> Thanks for the idea.

No problem.

Just for illustration purposes, I've pasted some code below.

-Roger

*<code>
oform1=Newobject("form1")
oform1.Show

Define Class form1 As Form

AutoCenter = .T.
Caption = "Form1"
Name = "Form1"

Add Object command1 As CommandButton With ;
Top = 184, ;
Left = 93, ;
Height = 27, ;
Width = 84, ;
FontBold = .T., ;
Caption = "<", ;
Name = "Command1"

Add Object command2 As CommandButton With ;
Top = 183, ;
Left = 181, ;
Height = 27, ;
Width = 84, ;
FontBold = .T., ;
Caption = ">", ;
Name = "Command2"

Add Object opglogical1 As opglogical With ;
ControlSource = "test.logfld", ;
Height = 47, ;
Left = 119, ;
Top = 78, ;
Width = 90, ;
Name = "Opglogical1", ;
Option1.Left = 5, ;
Option1.Top = 5, ;
Option1.Name = "Option1", ;
Option2.Left = 5, ;
Option2.Top = 24, ;
Option2.Name = "Option2"

Procedure Load
Create Cursor test (logfld L)
For i = 2 To 21
Insert Into test (logfld) Values (Iif(Mod(i,2)=0,.T.,.F.))
Next
Go Top In test
Browse Nowait
Endproc

Procedure command1.Click
Skip -1 In test
Thisform.Refresh
Endproc

Procedure command2.Click
Skip 1 In test
If Eof('test')
Skip -1 In test
Endif
Thisform.Refresh
Endproc

Enddefine

Define Class opglogical As OptionGroup

ButtonCount = 2
Value = 1
ControlSource = ""
Height = 46
Width = 71
Name = "opglogical"
Option1.Caption = "Option1"
Option1.Value = 1
Option1.Height = 17
Option1.Left = 5
Option1.Top = 5
Option1.Width = 61
Option1.Name = "Option1"
Option2.Caption = "Option2"
Option2.Height = 17
Option2.Left = 5
Option2.Top = 24
Option2.Width = 61
Option2.Name = "Option2"

Procedure value_assign
Lparameters vNewVal
If Vartype(vNewVal) = "L"
This.Value = Iif(vNewVal,1,2)
Else
This.Value = vNewVal
Endif

Replace (Justext(This.ControlSource)) ;
With Iif(This.Value = 1, .T.,.F.) ;
In (Juststem(This.ControlSource))
Endproc

Procedure value_access
Return Iif(This.Value = 1,.T.,.F.)
Endproc

Enddefine
*</code>