Hiding Object on Firm Works then it Doesn't

Hello, I hope you are all well and prosperous.

I have a need to have one checkbox show up on a form for a particular company and another checkbox to show up on the form for all other companies. Based on help from the forum on a prior thread, I have this working on the Job Entry form for the Firm checkbox using the following:

private void JobEntryForm_Load(object sender, EventArgs args)
{
	
	// Add Event Handler Code
	EpiCheckBox SetFirm_c = (EpiCheckBox)csm.GetNativeControlReference("598ffd4e-7406-4778-bb11-0e3c2a100c6e");
	EpiCheckBox chkFirm = (EpiCheckBox)csm.GetNativeControlReference("02844165-290f-418f-b7a9-200f4cb69ee2");
	if(oTrans.CoreSession.CompanyID== "FOO")
	{		
	    SetFirm_c.Visible = true;
		SetFirm_c.ReadOnly = false;
		chkFirm.Visible = false;
		chkFirm.ReadOnly = true;
	}
	else
	{		
	    SetFirm_c.Visible = false;
		SetFirm_c.ReadOnly = true;
		chkFirm.Visible = true;
		chkFirm.ReadOnly = false;
	}
}

}

I’ve given the custom checkbox (SetFirm_c) a red background for the purposes of this thread.

When the form is loaded from the FOO company, the custom checkbox is visible and the standard checkbox is hidden.
image

When the form is loaded from any other company, the custom checkbox is hidden and the standard checkbox is visible.
image

It all seems to work as designed. But when I retrieve data into the form, both checkboxes become visible
image

So why is the form load customization being ignored or over-written upon data load? I can guess that there is another form event that is being triggered that overrides the form Load rules. If that is the case, what form event do I need to apply the same custom logic to keep the intended checkboxes hidden?

Thanks for your input.

Michael

While it is not efficient, EpiViewNotification appears to solve these kind of issues.

1 Like

Please, please, please do not use EpiViewNotification for this purpose. As Jason says, it is not efficient - it is using a wrecking ball to kill a gnat.

The Epicor client is built around the concept that you apply properties to Data and not to Controls. In the Client you tell the Data that it is Red and all the controls that reference that data display it as red. This is done so that the data display is consistent regardless of what displays the data (control or grid) and even if a custom control is added and bound, it will have the same behavior as the Base controls. This is the magic behind Row Rules.

In this case you need to tell the Data that it is Hidden (isHidden Extended Properties) or Invisible (Row Rules). For optimal efficiency - and as your rule is managed at the company level - you should use the Extended Property Wizard (Tools>Wizards>Customization Wizards) to set the JobHead.JobFirm to isHidden True and then update the Customization created code with your Company specific logic.

You could also use a Row Rule but for this case, that would be a sledge hammer for offing your gnat…

3 Likes

Thanks to both Jason and Rich for chiming in on this thread. I am very new to C# and these deeper customizations of the Epicor UI – I really appreciate the help.

So I have it working using Rich’s suggestion to use the extended properties. After initializing the Extended Properties, the working code is as follows:

private void SetExtendedProperties()
{
	// Begin Wizard Added EpiDataView Initialization
	EpiDataView edvJobHead = ((EpiDataView)(this.oTrans.EpiDataViews["JobHead"]));
	// End Wizard Added EpiDataView Initialization

	// Begin Wizard Added Conditional Block
	if (edvJobHead.dataView.Table.Columns.Contains("SetFirm_c") && edvJobHead.dataView.Table.Columns.Contains("JobFirm"))
	{
		// Begin Wizard Added ExtendedProperty Settings: edvJobHead-SetFirm_c
		if(oTrans.CoreSession.CompanyID== "FOO")
		{
			edvJobHead.dataView.Table.Columns["SetFirm_c"].ExtendedProperties["IsHidden"] = false;
			edvJobHead.dataView.Table.Columns["JobFirm"].ExtendedProperties["IsHidden"] = true;
		}
		else
		{
			edvJobHead.dataView.Table.Columns["SetFirm_c"].ExtendedProperties["IsHidden"] = true;
			edvJobHead.dataView.Table.Columns["JobFirm"].ExtendedProperties["IsHidden"] = false;
		}
		// End Wizard Added ExtendedProperty Settings: edvJobHead-SetFirm_c
	}
	// End Wizard Added Conditional Block
}

I now realize that I have to add one more variable to my conditional statement.

CompanyID == FOO AND JobHead.FirmJob == false.  

What is the best way to reference the value of the JobHead.FirmJob column in the conditional statement?

Your original condition was based on Company which is a static value for the life of the UI so it was appropriate to do that work during Form Load with Extended Properties. Your new condition is not static and can change from one record to the next so you will need to use either a Row Rule with a Delegate condition or just create two Customizations - one for the FOO company and one for all the other companies.

If you go the two customization route, you can use simple Row Rules (no Delegate) - either way use the Action to set the data to Invisible.

Totally Agree with Rich here… Just a few weeks ago, spent some time “cleaning up” a customization in Sales Order, and reduced the time it took to create and save a sales order by 50%… most of that time was recovered by removing EpiViewNotification stuff, and/or setting/reading flags so that it would only run once per order (My first workaround). I found that some logic that was doing mass screen updates of custom tabs was running after every field change and multiple times per save.

Alright, so I looked into using a Delegate and could not figure it out – I need to dive into the C# syntax a bit deeper. If anyone has some sample code around using Delegates that they want to share, please send it. I found a couple of references in the 10.1.600 Customization User Guide and the Insights 2018 Customization to the Max book (yes, I do read manuals), but neither quite fit my need.

In the mean time, Rich’s last post pointed me in the right direction and I was able to accomplish my objective by using a Row Rule referencing the Company value on the row, instead of from the CoreSession. I created two row rules that hide one or the other checkboxes based on the Company on the row.

private void CreateRowRuleJobAsmblCompanyEquals_FOO()
{
	// Description: CompanyIsFOO
	// **** begin autogenerated code ****
	RuleAction disabledJobHead_JobFirm = RuleAction.AddControlSettings(this.oTrans, "JobHead.JobFirm", SettingStyle.Disabled);
	RuleAction invisibleJobHead_JobFirm = RuleAction.AddControlSettings(this.oTrans, "JobHead.JobFirm", SettingStyle.Invisible);
	RuleAction[] ruleActions = new RuleAction[] {
			disabledJobHead_JobFirm,
			invisibleJobHead_JobFirm};
	// Create RowRule and add to the EpiDataView.
	RowRule rrCreateRowRuleJobAsmblCompanyEquals_FOO = new RowRule("JobAsmbl.Company", RuleCondition.Equals, "FOO", ruleActions);
	((EpiDataView)(this.oTrans.EpiDataViews["JobHead"])).AddRowRule(rrCreateRowRuleJobAsmblCompanyEquals_FOO);
	// **** end autogenerated code ****
}


private void CreateRowRuleJobHeadCompanyNotEqual_FOO()
{
	// Description: CompanyIsNotFOO
	// **** begin autogenerated code ****
	RuleAction invisibleJobHead_SetFirm_c = RuleAction.AddControlSettings(this.oTrans, "JobHead.SetFirm_c", SettingStyle.Invisible);
	RuleAction[] ruleActions = new RuleAction[] {
			invisibleJobHead_SetFirm_c};
	// Create RowRule and add to the EpiDataView.
	RowRule rrCreateRowRuleJobHeadCompanyNotEqual_FOO = new RowRule("JobHead.Company", RuleCondition.NotEqual, "FOO", ruleActions);
	((EpiDataView)(this.oTrans.EpiDataViews["JobHead"])).AddRowRule(rrCreateRowRuleJobHeadCompanyNotEqual_FOO);
	// **** end autogenerated code ****
}

This appears to work, as when I load the record one or the other of the checkboxes disappears based on the Company value.

Here is the UI when in the FOO company. ( The checkbox with the red background is the SetFirm_c value.)
image

And here it is when in another company…
image

I did find, however, that it requires a bit of a UI tweak (cheat?) in order to function correctly.

In the finally deployment, I stack the two checkboxes on top of one another in the UI (same location coordinates). The SetFirm_c checkbox triggers a BPM for the FOO company. In order to ensure that it is the checkbox that is functional when the user is in that company, I have to bring it to the front and ensure that the JobFirm checkbox is behind it. Otherwise, the JobFirm checkbox gets checked even though it is supposed to be invisible. Not sure what is happening there, but I do have it working as needed.

Thanks, again, for all of your help with this.

Michael

In many cases, the forms logic will change properties of the native controls - this includes enabling/disabling.

The easy solution is to move the control off screen if possible. A second option is breaking the EpiBinding of the control because in many cases, this is what drives the logic in the background.

As a final solution, one that I have used in the past, is to add a PropertyChanged event on the offending control. When it fires, you can force it back hidden and/or bring your control to the front.

1 Like