Create a custom EpiListBox

Hello!

Has anyone successfully created/used a custom EpiListBox control?

1 Like

What are you trying to do? You should have UltraWinListView which is the “listbox” like control

Hey Aaron,

I’m trying to build out a framework that allows our users to exempt certain customers from certain warehouses. Instead of having a checkbox for each warehouse (3) in total for each exemption, id like to have one control that can dynamically add warehouses to a ~ delineated list.

I’ll loop through this list in a BPM to check if a customer in question is eligible to ship from said warehouse.

The left and right sided box thing what you’re looking for?

image

// Script head
EpiListPickerPanel _atrpnl;
BAQDataView _bdvAttribut;
 
// Initialize custom code
_atrpnl = new EpiListPickerPanel();
SetupAttrListControl();
SetupAttributView();
 
// Method to handle your setup
public void SetupAttrListControl()
{
    pnl1.Controls.Add(_atrpnl);
       _atrpnl.PreserveSourceList = false;
    _atrpnl.ReadOnly = true;
 
    /** The following is broken down into a few simple parts. It generates a string list delimited by whatever character you would like
    ** This is only one of many implementations of InitDataBind. A screenshot above shows all of them. This is the only one I know how to use. 
    ** It was modeled after the attributes in Customer Entry
    ** @SourceDataView (string) - This is the dataview containing the values for your source (left) list
    ** @SourceValueMember (string) - Think of this in terms of the dropdown list Value Member
    ** @SourceDisplayMember (string) - Think of this in terms of the dropdown list Display Column
    ** @StringDelimiter (char) - This is the character that you would like to use to seperate your values. Epicor typically uses ~ but you may use whatever suits your need
    ** @TargetColumn (string) - The column binding to insert the delimited string into
    ** @TargetDataView (string) - The dataview that your column to insert the string into resides.
    ** @Trans (EpiTransaction) - duh....
    **/
    _atrpnl.InitDataBind("Attribut", "Attribut_AttrCode", "Attribut_AttrDescription", ',', "AttrList", "AttrList", oTrans);
}
 
// Use a BAQ for the source list if the list you need can't be found in the native oTrans or able to be created in FKV
public void SetupAttributView() 
{
    _bdvAttribut = new BAQDataView("WCI-AttributeList");
    oTrans.Add("Attribut", _bdvAttribut);
    RefreshAttributView();
}
6 Likes

wow beautiful! Thank you very much.

They need to add this control into the toolbox for easier access :slight_smile:

Add it to feature requests maybe someone reads those :smiley:

Just an FYI, I couldnt get a BAQ Dataview working so I used a dynamic query adapter and created a new EpiDataView to populate the source list:

public EpiListPickerPanel whseSwitchPickerControl;
public DataTable baqWarehouses;
public EpiDataView whsePickEdv;

public void SetupWarehouseView() 
{
    DynamicQueryAdapter myDqa = new DynamicQueryAdapter(oTrans);
	myDqa.BOConnect();
	QueryExecutionDataSet myQeds = myDqa.GetQueryExecutionParametersByID("Warehouses");
	myQeds.ExecutionParameter.Clear();
	myDqa.ExecuteByID("Warehouses", myQeds);

	baqWarehouses = myDqa.QueryResults.Tables["Results"];
	whsePickEdv = new EpiDataView(false,"whseView");
	whsePickEdv.dataView = baqWarehouses.DefaultView;
	oTrans.Add("WarehouseView", whsePickEdv);
	
}

private void InitalizeWhseSwitchPicker()
{
	WhseSwitch.Controls.Add(whseSwitchPickerControl);
	whseSwitchPickerControl.PreserveSourceList = false;
	whseSwitchPickerControl.SourceString = "Warehouses";
	whseSwitchPickerControl.TargetString = "Exempt Warehouses";
	whseSwitchPickerControl.Height = 260;
	whseSwitchPickerControl.InitDataBind("WarehouseView", "Warehse_WarehouseCode", "Warehse_WarehouseCode", '~', "WhseExemptList_c", "Customer", oTrans );	
}

You didn’t include that function in your code block, what is it supposed to contain?

What function?

In your SetupAttributView function you call RefreshAttributView - not sure what is needed in there.

I think I figured it out for myself, I used the following code in place of RefreshAttributView

MethodInfo mi = _bdvAttribut.GetType().GetMethod("invokeExecute", BindingFlags.Instance | BindingFlags.NonPublic);
    	mi.Invoke(_bdvAttribut, new object[]{ true });

You got 'er

1 Like

In case anyone else is trying this and is noticing their listboxes not being updated, you need to notify the EpiDataViews whenever you select or deselect anything. EpiListPickerPanel has a PickerListChanged event and a PickerListChangedEventHandler for this.
This stumped me for longer than I care to admit.

Hi @tmanjrekar,
is it possible to share the full code in here please ?

Sure. I did the main setup according to Joshua and Evan’s snippets above. Then added the following:

public void InitializeCustomCode()
{
	// Whatever other code you have
	myEpiListPickerPanel.PickerListChanged += new EpiListPickerPanel.PickerListChangedEventHandler(myEpiListPickerPanel_ListChanged);
}

public void DestroyCustomCode()
{
	// Whatever other code you have
	myEpiListPickerPanel.PickerListChanged -= new EpiListPickerPanel.PickerListChangedEventHandler(myEpiListPickerPanel_ListChanged);
}

private void myEpiListPickerPanel_ListChanged()
{
	oTrans.NotifyAll();
}

Another thing I noticed the other day was that clearing the form cleared the BAQDataView as well, so if I loaded something after a clear, my picker list wouldn’t show anything. This might not be an issue if it’s subscribed to something else (maybe? I haven’t really tested this). But since my BAQ shares no fields with any of the EpiDataViews on the screen, I had to refresh it after a clear.

private void YourForm_AfterToolClick(object sender, Ice.Lib.Framework.AfterToolClickEventArgs args)
{
	if (args.Tool.Key == "ClearTool")
	{
		// This is the snippet that calls invokeExecute()
		RefreshAttributView();
	}
}
1 Like

many thanks for that pal :+1:

I also struggled getting the BAQDV to work. I think the missing puzzle piece is that the BAQDV needs to get setup before creating the custom control. I swapped the order in the InitializeCustomCode section and that got it working.

SetupAttributView();
_atrpnl = new EpiListPickerPanel();
SetupAttrListControl();

Thanks to everyone else who posted in here.

Has anyone from this thread ever come across any documentation for the EpiListPickerPanel? I’d really like to see what events the buttons fire when adding/removing items from one list to the other. TIA.

The only documentation I could find was to use ILSpy and open up Ice.Lib.EpicLientLib.dll.

1 Like

I don’t see the point. Every button in the LPP just changes the associated list. So the _ListChanged event covers just about everything.

The one issue I ran into with LPP is that, if you have a large list, it can scale beyond the form size.

//You'd think this would be enough.
lpp.AutoSize = false;
lpp.Width = 526;
lpp.Height = 531;
//But I needed this to lock it down entirely.
var max = new System.Drawing.Size(230, 500);
lpp.Controls["lbSourceList"].MaximumSize = max;
lpp.Controls["lbTargetList"].MaximumSize = max;

@jeromy and @jtownsend - Thanks to both of you. I did eventually manage to locate the DLL in ILSpy to see what was there. I wasn’t sure if the lbSourceList and lbTargetList were used in the data transfer or if they were just there to display what the LPP.SourceList and LPP.TargetList values were… and if the moving of the data was done on the LPP. But if it’s done using the LB controls, I think I can go from there.

Again, thanks for the help. I feel much more able to solve the problem today.