Epicor Insights 2019 Customization Tips Tricks and Troubleshooting Code

Hello All,
As promised here is the code demonstrated in the Tips Tricks and Troubleshooting session at Insights. Note this code is provided AS IS and it is not intended to be used in production. If it breaks your stuff that’s on you!

I will NOT support this going froward, feel free to ask questions and I’ll try to answer them but do not expect a quick turn around.

  1. Bulk Apply Credit Memos
    The majority of the code presented was used in conjunction with this customization. You can download the zip file here with all the code.
    CrossApplyCM.zip (59.1 KB)
    Note contents include 2 BAQs and 2 Customizations one for UD01 and one for Apply Credit Memo
    Here is a video of the Customization in Action

The emphasis of this demo was a focus on “EpiMagic” such as BAQDataViews , CallBackContext and a few others.

  1. Auto Sequence: This is a piece of code that can be run on a BPM to generate a self incrementing Auto Sequence Number (1,2,3,4,5) etc.
new Ice.Lib.NextValue(Db).GetNextSequence("CAPSeq").ToString("00000000")
  1. Refresh and Clear BAQ DataViews: This is a little function which allows you to refresh and or clear BAQDataViews since this isn’t supported nativelly.
 private void RefreshBAQDataView(BAQDataView iBaqView)
    {
        MethodInfo mi = iBaqView.GetType().GetMethod("invokeExecute", BindingFlags.Instance | BindingFlags.NonPublic);
        mi.Invoke(iBaqView, new object[]{ true });
    }
      
    private void ClearBAQDataView(BAQDataView iBaqView)
    {
        FieldInfo dqAdapter = iBaqView.GetType().GetField("dqAdapter", BindingFlags.Instance | BindingFlags.NonPublic);
        Ice.Adapters.DynamicQueryAdapter dsQ = (Ice.Adapters.DynamicQueryAdapter)dqAdapter.GetValue(iBaqView);
        dsQ.QueryResults.Clear();
    }

I’m sure @rbucek will be posting his code and samples as soon as he is able to. Stand By

9 Likes

re Auto Sequence, you can also SET (or reset) the next sequence number:
NextValue(Db).SetSequenceCurrentValue("CAPSeq", 1000)

1 Like

Sorry for the long delay everyone. I flew straight from insights out to the coast for a couple weeks and life has been hectic ever since. Here are the code snippets from my portion of the presentation with @josecgomez on UI interactions and Infragistics controls. If you have any questions, feel free to reach out to me.

image

  1. Clear controls (you want to flush a large number of filters in a dashboard for ex.)
using Infragistics.Win.UltraWinGrid;
using System.Collections.Generic;

public class Script
{

	public void InitializeCustomCode()
	{
		this.btnClearFilters.Click += new System.EventHandler(this.btnClearFilters_Click);
	}

	public void DestroyCustomCode()
	{
		this.btnClearFilters.Click -= new System.EventHandler(this.btnClearFilters_Click);
	}

	private void btnClearFilters_Click(object sender, System.EventArgs args)
	{
        Ice.Lib.Framework.EpiBasePanel pnl = (Ice.Lib.Framework.EpiBasePanel)csm.GetNativeControlReference("9fc6a346-e062-4c54-a790-6e37882f4463");
        foreach (Control c in pnl.Controls)
        {
            if (c.GetType() == typeof(EpiTextBox))
                c.Text = string.Empty;
            if (c.GetType() == typeof(EpiNumericEditor))
            {
                ((EpiNumericEditor)c).Value = null;
            }
            if (c.GetType() == typeof(EpiCombo))
            {
                c.Text = string.Empty;
            }
            if (c.GetType() == typeof(EpiDateTimeEditor))
            {
                c.Text = string.Empty;
            }
            if (c.GetType() == typeof(EpiTimeEditor))
            {
                c.Text = string.Empty;
            }
        }				
	}

    // You can also reference native Epicor objects in this manner when you are going to reference it throughout your customization
    EpiBasePanel myPanel
    {
        get
        {
            return (EpiBasePanel)csm.GetNativeControlReference("9fc6a346-e062-4c54-a790-6e37882f4463");
        }
    }
}
  1. Filter a dashboard grid with a separate DateTimePicker and a TimerPicker. This uses a minutes past an epoch integer column for tracker query control
using Infragistics.Win.UltraWinGrid;
using System.Collections.Generic;

public class Script
{

	EpiTextBox epiCalculated_numLastPacked;

	public void InitializeCustomCode()
	{
		this.edeLastPackedDate.Validating += new System.ComponentModel.CancelEventHandler(this.edeLastPackedDate_Validating);
		this.eteLastPackedTime.Validating += new System.ComponentModel.CancelEventHandler(this.eteLastPackedTime_Validating);

		epiCalculated_numLastPacked = (EpiTextBox)csm.GetNativeControlReference("fd40bea2-2cda-4f4b-b86c-adf9bbee8af6");
	}

	public void DestroyCustomCode()
	{
		this.edeLastPackedDate.Validating -= new System.ComponentModel.CancelEventHandler(this.edeLastPackedDate_Validating);
		this.eteLastPackedTime.Validating -= new System.ComponentModel.CancelEventHandler(this.eteLastPackedTime_Validating);
	}


	private void edeLastPackedDate_Validating(object sender, System.ComponentModel.CancelEventArgs args)
	{
        if(eteLastPackedTime.Value != null && edeLastPackedDate.Value != null)
        {
            Calc_numLastPacked();
        }
	}

	private void eteLastPackedTime_Validating(object sender, System.ComponentModel.CancelEventArgs args)
	{
        if (edeLastPackedDate.Value != null && eteLastPackedTime.Value != null)
        {
            Calc_numLastPacked();
        }
	}

	private void Calc_numLastPacked()
	{
		DateTime dt;
		DateTime dt1;
		if(DateTime.TryParse(edeLastPackedDate.Value.ToString(), out dt) && DateTime.TryParse(eteLastPackedTime.Value.ToString(), out dt1))
		{
			TimeSpan span = dt - Convert.ToDateTime("2000-01-01");
			TimeSpan span1 = dt1 - Convert.ToDateTime(DateTime.Today);
			epiCalculated_numLastPacked.Value = ((int)span.TotalMinutes + (int)span1.TotalMinutes).ToString();
		}
	}
  1. How we select and deselect, or update columns in rows in a grid through through highlighting, button clicks etc
using Infragistics.Win.UltraWinGrid;
using System.Collections.Generic;

public class Script
{
    EpiUltraGrid myPackGrid;
    EpiUltraGrid myDetailGrid;
    List<UltraGridRow> gatherRows;
	string user;

	public void InitializeCustomCode()
	{
        myPackGrid = (EpiUltraGrid)csm.GetNativeControlReference("e9860346-a5da-4352-9e89-e1d3137599de");
        myDetailGrid = (EpiUltraGrid)csm.GetNativeControlReference("eddfa7cc-e133-4f5d-95e0-bb7dda5268e9");
        gatherRows = new List<UltraGridRow>();
        var CCCData = oTrans.Factory("CallContextClientData");
        user = CCCData.dataView[CCCData.Row]["CurrentUserId"].ToString();
	}

	private void btnSelectAllPacks_Click(object sender, System.EventArgs args)
	{
        // Get all the rows
        GatherRows(myPackGrid.Rows, "Calculated_Release", false);
        // Change a column value on those rows
        ChangeField(myPackGrid, gatherRows, "Calculated_Release", true);
	}

    private void btnClearAllPacks_Click(object sender, System.EventArgs args)
	{
        GatherRows(myPackGrid.Rows, "Calculated_Release", true);
        ChangeField(myPackGrid, gatherRows, "Calculated_Release", false);
	}

    private void btnSelectHighlightedPacks_Click(object sender, System.EventArgs args)
	{
        // Use linq to grab all rows the user highlighted with their mouse that aren't groupby rows
        List<UltraGridRow> gridRows = (from UltraGridRow r in myPackGrid.Selected.Rows
                                                             where Convert.ToBoolean(r.Cells["Calculated_Release"].Value).Equals(false)
                                                             && r.GetType() != typeof(UltraGridGroupByRow)
                                                             select r).ToList();
        ChangeField(myPackGrid, gridRows, "Calculated_Release", true);
	}

    private void ChangeField(UltraGrid grid, List<UltraGridRow> gridRows, string field, bool val)
    {
        /* SuspendRowSynchronization and ResumeRowSynchronization methods can be used to temporarily 
        suspend UltraGrid from responding to data source change notifications. When row syncrhonization 
        is suspended, the UltraGrid will still mark the rows dirty so it will re-create the rows next time it gets painted. */
        if (gridRows.Count > 0)
        {
            try
            {
                myPackGrid.BeginUpdate();
                myPackGrid.SuspendRowSynchronization();
                foreach (var row in gridRows)
                {
                    //Check and uncheck the boxes we want
                    row.Cells[field].Value = val;
                }
            }
            catch 
            { 
                //Do some error handling here
            }
            finally
            {
                // Clean up
                myPackGrid.ResumeRowSynchronization();
                myPackGrid.EndUpdate();
                gatherRows.Clear();
            }
        }
    }

    private void GatherRows(RowsCollection row, string field, bool val)
    {
        List<UltraGridRow> gridRows = new List<UltraGridRow>();
        foreach (UltraGridRow r in row)
        {
            if (r.GetType() == typeof(UltraGridGroupByRow))
            {
                // A recursive query that gets to the bottom of things
                GatherRows(((UltraGridGroupByRow)r).Rows, field, val);
            }
            else
            {
                if(r.Cells[field].Value.Equals(val))
                {
                    // Add this to our collection of stuff to do
                    gatherRows.Add(r);
                }
            }
        }
    }
}
  1. Invoke a tool click on tool bar items programatically
using Infragistics.Win.UltraWinGrid;
using System.Collections.Generic;

public class Script
{

	public void InitializeCustomCode()
	{
		this.btnRefresh.Click += new System.EventHandler(this.btnRefresh_Click);

		// End Wizard Added Custom Method Calls
	}

	public void DestroyCustomCode()
	{
		this.btnRefresh.Click -= new System.EventHandler(this.btnRefresh_Click);
	}

	private void btnRefresh_Click(object sender, System.EventArgs args)
	{
		ToolBarClick("RefreshTool");
	}

    private void ToolBarClick(string tool)
    {
        MainController.AppControlPanel.HandleToolClick(tool, new
        Infragistics.Win.UltraWinToolbars.ToolClickEventArgs(MainController.MainToolManager.Tools[tool], null));
    }
}
  1. Save a grid layout via a checkbox to a temp directory as an xml file and automatically restore the layout to what it was at the time of save by unchecking the box.
using Infragistics.Win.UltraWinGrid;
using System.Collections.Generic;
using System.IO;
using System.Drawing;

public class Script
{
    public string tempFile = string.Empty;

    public void InitializeCustomCode()
    {
        this.cbxPrintMode.CheckStateChanged += new System.EventHandler(this.cbxPrintMode_CheckStateChanged);
    }

    public void DestroyCustomCode()
    {
        this.cbxPrintMode.CheckStateChanged -= new System.EventHandler(this.cbxPrintMode_CheckStateChanged);
    }

    private void cbxPrintMode_CheckStateChanged(object sender, System.EventArgs args)
    {
        // ** Place Event Handling Code Here **
        if (cbxPrintMode.CheckState.ToString() == "Checked")
        {
            MessageBox.Show("You will only be able to print jobs with material issued.  Issue Material function will be disabled in Print Mode.");
            tempFilePM = Path.GetTempFileName().Replace(".tmp", ".xml");
            myGrid.DisplayLayout.SaveAsXml(tempFilePM);
            btnIssue.Visible = false;
            btnIssue.ReadOnly = true;
            btnSS.Visible = true;
            btnSS.ReadOnly = false;
            btnPrintAll.Visible = true;
            btnPrintAll.ReadOnly = false;
            myGrid.DisplayLayout.Bands[0].SortedColumns.Clear();
            myGrid.DisplayLayout.Bands[0].SortedColumns.Add("UD10_Lot_Num_c", true);
            shpPrintMode.Visible = true;
            shpPrintMode.Enabled = true;
            shpPrintMode.Status = StatusTypes.Warning;
            shpPrintMode.EnabledCaption = "**** PRINT MODE ****";
        }
        if (cbxPrintMode.CheckState.ToString() == "Unchecked")
        {
            myGrid.DisplayLayout.LoadFromXml(tempFilePM);
            File.Delete(tempFilePM);
            MainController.AppControlPanel.HandleToolClick("RefreshTool", new Infragistics.Win.UltraWinToolbars.ToolClickEventArgs(MainController.MainToolManager.Tools["RefreshTool"], null));
            btnIssue.Visible = true;
            btnIssue.ReadOnly = false;
            btnSS.Visible = false;
            btnSS.ReadOnly = true;
            btnPrintAll.Visible = false;
            btnPrintAll.ReadOnly = true;
            shpPrintMode.Visible = false;
            shpPrintMode.Enabled = false;
        }
    }
}

Was really great seeing everyone there this year. Looking forward to next!

5 Likes

Jose, I am getting these messages when I try to compile this code, what am I missing in my using statements/references?

Error: CS0246 - line 72 (1032) - The type or namespace name ‘MethodInfo’ could not be found (are you missing a using directive or an assembly reference?)
Error: CS0103 - line 72 (1032) - The name ‘BindingFlags’ does not exist in the current context
Error: CS0103 - line 72 (1032) - The name ‘BindingFlags’ does not exist in the current context

using System.Reflection;

image

image

:sweat_smile: