Configurator OnValidate Infinite loop


(Evan Purdy) #1

I have the following code for an decimal input in its OnValidate event. It is supposed to force sales to enter a value for DecISBLength that is a multiple of 1/16 by rounding for them, but if an engineer is using the configurator allow any value to be entered.

The problem is this line: Inputs.DecISBLength.Value = RoundedInput;
Even though when I display the value for RoundedInput via a message box, the OnValidate event is called endlessly with the original value and not the rounded value. If I comment out this line the infinite loop is cured. I don’t understand how the event gets the old value, its like the event is triggering before the value is fully set.

Can anyone figure out what is going on? I am stumped.

// This is copied to each input that needs to be a multiple of 1/16. This is becuase you cannot use client side UD methods in the OnValidate event, and the OnChanged event happens after the value has already changed, so cannot be used to prevent invalid inputs.
var InputValue = Inputs.DecISBLength.Value;
if (InputValue % 0.0625m > 0m)
{
	var RoundedInput = Math.Round(InputValue * 16m) / 16m;
	if (Inputs.EngineeringBypass.Value == true)
	{
		var DialogMessage = string.Format("Input value ({0}\") was not a multiple of (1/16)\", round to the nearest sixteenth? (Would be {1}\" (Engineering override enabled)", InputValue, RoundedInput);
		var Result = MessageBox.Show(DialogMessage, "Round input?", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation);
		if (Result == System.Windows.Forms.DialogResult.Yes)
		{
			Inputs.DecISBLength.Value = RoundedInput;
			ValidateArgs.Cancel = true;
		}
		else
		{
			ValidateArgs.Cancel = false;
		}
	}
	else
	{
		ValidateArgs.Cancel = true;
		var DialogMessage = string.Format("Input value ({0}\") was not a multiple of (1/16)\", rounding to the nearest sixteenth: ({1}\")", InputValue, RoundedInput);
		MessageBox.Show(DialogMessage, "Invalid Precision", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
		Inputs.DecISBLength.Value = RoundedInput;
		return;
	}
}
ValidateArgs.Cancel = false;

(Monty Wilson) #2

Evan, that line appears twice in your code. Which instance can you comment-out and stop the infinite loop?


(Evan Purdy) #3

The second, I haven’t tested with the engineering override checkbox set yet, but I would guess that both lines would cause the infinite loop.


(Monty Wilson) #4

Dear Evan,

The error is triggered when you set the property of Inputs to a value, but we don’t see what’s being passed-in here. Have you tried going to the code that calls this code, and passing by value instead of reference? When you try to set the input value of a method to a different value inside the method, I can see where that might trigger another Validate event.

Best,
…Monty.


(Evan Purdy) #5

There are no parameters, this is attached to the validate event for Inputs.DecISBLength not a UD method. You can see that the InputValue is assigned at the top.


(Monty Wilson) #6

InputValue yes, it’s a declared variable. Since this code is attached to the validate event for Inputs.DecISBLength, and the code that triggers it attempts to set the very same thing to a value, I wonder if there is another way of getting the rounded number in there (instead of just using assignment to .Value) that would bypass the validation feature. Then it wouldn’t recurse. …M.


(Evan Purdy) #7

I tried making a check box that is set while it is currently validating but it didn’t help because even on the second validate event it only has the original value and not the new rounded one, which makes no sense to me as the rounded value is what is triggering the validate event again…


(Evan Purdy) #8

Well, regardless of my specific problem does anyone have an idea how to achieve what I was tying to do?

I want a decimal input to be limited to multiples of 1/16 and round anything else entered to a multiple of 1/16 EXCEPT if an engineering checkbox is set in which case I want to ask before rounding, and allow them choose not to round but keep the exact value if desired.


(Roger Bomford ) #9

Hi Evan,

Here’s a suggestion utilizing built in increment precision:

Set the decimal field Increment to .0625 on all fields that you wish to enforce 1/16 fraction validation. Print out a US fraction to US decimal conversion chart and distribute to configurator entry team. Ask them to keep chart handy. This will force validation of 1/16 increments, and provide them with the correct decimal values to correct entry errors. If engineering checkbox is checked- write client UD method and place in On Field Changed in all fields that you wish to remove increment validation. You can remove (or add back) increment validation on decimal fields programmically by using the Inputs.decWidth.Increment = 0; or Inputs,decWidth.Increment = .0625; (Input field = decWidth) If eng chkbox is checked, then write additional code to subtract integer value from total value leaving only the decimal portion, if decimal portion does not divide by 1/16 then popup up message box informing eng team that value will be accepted but is not 1/16 divisible. If eng checkbox is later unchecked, then you’d need to add back via code the Increment of .0625, and optionally could clear the value forcing the user to re-enter.

Thanks,

Roger


(Chris Conn) #10

Arent your ValidateArgs.Cancel assignments all backwards?

When you set Cancel = true, the expected action is to STOP the input from changing (reverting to previous value). Your endless loop is caused because, you are changing the value in the call, which will again try to validate

I am not versed in Configurator-specific stuff (i understand it’s a bit different from a normal customiization). Is there any way to use a different event on the field? Maybe the Leave() event of the control?


(Evan Purdy) #11

I decided it was good enough to just set the increment to 0.625 by default and then if the engineering override checkbox is clicked set the increment to zero so any number can be entered.