Clicking On/Off a Checkbox

Let’s say I’m a data entry person who opens up any general data entry form within Epicor ERP that contains a checkbox control.

I request a “new record” from the text menu at the top of my form.

I start filling out data on the form until I get to the checkbox.

I click on the checkbox.

I decide that I shouldn’t have clicked on the checkbox, so I uncheck it.


What have I done in terms of saving data to the database, or in terms of modifying the data view, or in terms of affecting the “state” of the form, or in terms of affecting the “state” of the checkbox control… by performing these simple clicking actions?

At what level of processing am I when I merely click on/off a checkbox - and - can this particular level of processing be accessed/affected via custom C# code?

Depends on the checkbox.
If it’s a basic flag, it might do nothing at all.
If it controls other fields (like checking the One Time Ship To), it both enables the fields and may auto-populate them.
It may actually drive actions to occur. The checkbox next to “Unapproved” on PO entry actually fires actions to save the record (and possibly create others)

  1. Enable tracing
  2. Check the checkbox
  3. Un-check the checkbox
  4. Disable tracing
  5. View Trace log.
1 Like

Thanks, Calvin.

I’ve already performed this step. To be a bit more precise, I’m specifically interested in the behavior of the “ckbTMBilling” control on the Sales Order Entry form (Erp.UI.App.SalesOrderEntry.SalesOrderForm).

Trace log show nothing going on behind the scene after clicking on that control, on and off, three consecutive times, for a total of 6 clicks.

There are no properties that I can isolate related to that control’s value (true/false), or its checked “state” (true/false):

I can access the data view:

EpiDataView edvOrderDtl; 
edvOrderDtl = ((EpiDataView)(this.oTrans.EpiDataViews["OrderDtl"]));
DataRow edvOrderDtl_Row = edvOrderDtl.CurrentDataRow;

… and assign the value to a variable:

var varTMBilling = edvOrderDtl_Row["TMBilling"];

I can also address it from the Ice framework:

Ice.Lib.Framework.EpiCheckBox chk = (Ice.Lib.Framework.EpiCheckBox)ctrl;

… and try to modify its checked state:

chk.Checked = false;

The problem is that any attempt to modify, by custom C# code, the checked state of this control - the results never show up on the form.

I’ve tried “oTrans.Refresh” and “oTrans.Update” (in the case of modifying the data view), but this produces a lot of record state errors.


So – the question was more in general terms because I’m not looking to adjust data related to the state of the checkbox… I’m looking to control, from a data validation and work-flow process, if the checkbox should be checked, or not.

It’s more of this type of situation:

  1. User clicks on that checkbox
  2. Message box is presented to inquire if the user meant to place a check in the box
  3. User responds “yes”; conditional takes over and logs that confirmed answer, leaving the check in place – OR …
  4. User responds “no”; conditional takes over and clears the checkbox for them

It’s the last part in bold that I’m having trouble with.

Is there some magical trick to simply clear the checked state of a checkbox without getting into the data view and refreshing the form?

1 Like

So you want this to happen the instant the box is checked? and not during a DB update?

Correct.

if you are explicitly grabbing the control (via csm and guid) and then modifying the checked state, I cant imagine it would not update on the form. With that said, as Calvin eluded to, there are certain checkboxs which drive other processes. This are generally triggered by leaving the field.

You could try:
myCheck.Focus();
myCheck.Checked = true or false;
focus a different control here.

this should ensure the processing code gets triggered on change.

I’ve seen a few questions you are posting in the forum and a few of them lately have been dealing with control modification via code. I recommended this before and will do so again.
In the Epicor Paradigm Controls themselves are driven from databindings to an EpiDataView. Most (if not all) changes should be done via the dataview and let the EpiMagic update the controls and the screen as appropriate.
Updating the Checked / UnChecked state of the control may or may not trigger the right logic in the data set side of things.
My Recommendation is that you grab a hold of your dataview set the value and call a Notification event which will then take care of updating the control.

Example

EpiDataView edv = oTrans.Factory("OrderDtl");
edv.dataView[edv.Row].BeginEdit();
edv.dataView[edv.Row]["TMBilling"]= true; //Or false
edv.dataView[edv.Row].EndEdit();
edv.Notify(new EpiNotifyArgs(this.oTrans, edv.Row, edv.Column);

Hope this helps, and again always try to find a way to modify the underlying data-view not the control state itself. Though this is not impossible to do, you’ll have a lot more luck with this approach.

I am nothing if not persistent on this particular subject just ask @Chris_Conn :laughing: but it is for a good reason. Control driven programming within the Epicor Framework goes against the Frameworks paradigm and you’ll be fighting your way up stream the whole time.

4 Likes

I’ll try it using the focus property, as you suggested, and see if that’ll give me some headway.

Full disclosure – I did not work the issue from the explicit csm/GUID reference. Maybe that’s my issue?

Thanks, Jose.

I believe its more of a foundational misunderstanding about control behavior that I’m tripping on. I’ve seen several of your responses, not only to me, but to others, explaining the data binding of controls. I get that piece of it.

What I don’t seem to understand, even in reading the numerous discussions on the topic, is how clicking on a checkbox that does not seem to log any action in the trace log, would bind an untraceable action back to the data view. Now, it’s certainly possible that I’m not setting up the data view references/calls correctly, and that I can certainly concede. In this particular case, working with the data view is producing errors (when I set that back up, I can post them here in the thread).

So… you understand it. Others understand it. I can appreciate that - truly… and… I’m glad you’re being as patient as you can. Don’t give up - I’m almost there!

It’s like trying to teach fractions to a person whose only frame of reference is the base-10 metric system. It’s going to take a while to sink in.

I’m not sure I follow, what happens when you check the checkbox that you think shouldn’t happen?

You can’t use the wizard for events of built-in controls.

Try a Form Event of type AfterFieldChange, for table OrderDtl

ok I have read more thoroughly what you are trying to do. In this case you should use the BeforeFieldChanged event in the data view. This is an event that is raised as soon as the change is made in the datafield (anywhere)

This will generate this code in which you can put your logic. The reason to use the “before” event is because the data hasn’t been yet committed and can be “canceled” via resetting the proposed value.

private void OrderDtl_BeforeFieldChange(object sender, DataColumnChangeEventArgs args)
	{
		// ** Argument Properties and Uses **
		// args.Row["FieldName"]
		// args.Column, args.ProposedValue, args.Row
		// Add Event Handler Code
		switch (args.Column.ColumnName)
		{
			case "TMBilling":
                        {
                                //Here check if args.ProposedValue == true then raise your message box, if they click No, set args.ProposedValue = false;
                        }
				break;
		}
	}
1 Like

Jose is right…per usual. EpiMagic is way to go. It has made my life easier in the long run. There are certain situations I still run into from time to time where control modification is easier (or necessary), but in most cases, dataViews for the win.

José:

Yes. That is how I originally set up this solution - through the form event wizard (code start shown here):

private void OrderDtl_BeforeFieldChange(object sender, DataColumnChangeEventArgs args)
{
	switch (args.Column.ColumnName)
	{
		case "TMBilling":
			if (Convert.ToBoolean(args.ProposedValue) == true)
			{
				EpiDataView edvOrderDtl; 
				edvOrderDtl = ((EpiDataView)(this.oTrans.EpiDataViews["OrderDtl"]));
				DataRow edvOrderDtl_Row = edvOrderDtl.CurrentDataRow;

I’m just checking to see if this checkbox “proposed value” is set to true at any time. If so, start processing some data validation assistance for the user.

Quick backstory – we’re having trouble with people clicking on this checkbox which places the sales order in an “on hold” status, as well as creates multiple invoices for the same order. This is a problem for us and we want to track it.

So… the intended validation flow is something like this:

Everything works… it will log the decision to leave that checkbox checked after forcing someone to acknowledge it. But - I can’t perform a simple “clear” of the checkbox if someone made a mistake and clicks on “No” to the acknowledgement message box.

In the “no” conditional, I’ve tried this:

foreach (Control ctrl in parentControl.Controls)
{
	if (ctrl.Name.EndsWith(strCtrlName))
	{
		Ice.Lib.Framework.EpiCheckBox chk = (Ice.Lib.Framework.EpiCheckBox)ctrl;
			chk.Checked = false;
	}
}

… where “strCtrlName” had previously been defined as “ckbTMBilling” (which was verified)… and this processes without error - BUT - with no actual visual indication on the form that the control’s “Checked” property had been set to “false”.


EDIT:

I just saw the code notation you had referenced where it states:

if they click No, set args.ProposedValue = false;

Is this the direction I should be traveling?

The answer on that would appear to be “Yes”, because I just tested it.

That was the magic I was looking for… just clear the checkbox for the user.

This is why people like me get confused on addressing the data view in this specific type of situation. I do understand the data binding aspect of data views… but this did not seem to be a “data” function, in my mind (again… fractions versus base-10 mentality).

Thanks for being patient, José, Chris, Calvin… much appreciated. You guys pointed me in the right direction and I can’t thank you enough.


I’m setting José’s example above as the solution. For those reading this looking for answers - you’ll want to specifically focus on where José states in the CASE block:

// Here check if args.ProposedValue == true then raise your message box, if they click No, set args.ProposedValue = false;

What clears the checkbox control (in this specific situation) is:

set args.ProposedValue = false;


4 Likes

Hey all, stumbled upon this post while looking for some guidance. Could I follow similar logic and disable a checkbox after it has been checked ? I was requested to not allow users to uncheck the ship checkbox in transfer shipment entry after it has already been set to shipped.

You might start a new topic and reference this post with your query, however for your example I would think you would want the control to become disabled/readonly once set to true by using the ExtendedProperties of the dataview.

@mstegnjaic - If it’s already been checked, couldn’t you do a Pre-BPM on the update with a condition of ‘ changed from true to false’, and pop-up an exception?

Thats exactly what I did !! I was hoping to get the button to become fully inactive though. Through the custom code widget, can you reference the enable property for a control ?