Problem displaying a drop down list in a field on a grid

Version: 10.1.600.11 (Dedicated Tenant)

I have created an Extended UD Field (FinishSteps_c) on a UD Table (UD01) that derives it’s value from a User Code(UD01.STEPS) referenced on the field’s extended properties. When adding new rows to this table, users will be using the list view to fill in all the required fields. When selecting the FinishSteps_c field, I would like a drop down list to display with only the available codes from UD01.STEPS. I am trying to accomplish this using this method, but I keep receiving this error when I load the customization:

 Error Detail 
 ============
 Message: Exception has been thrown by the target of an invocation.
 Inner Exception Message: Key not found: 'FinishSteps_c'
 Parameter name: key

What’s odd is that I only receive this error when the referenced column is an extended UD Field. If I specify a Custom Field like Character08 or a Key field it works without issue. I’ve attached my code for reference. Any help would be greatly appreciated as this issue has me stumped.

UD01Form_CustomCode.txt (1.6 KB)

myGridList.DisplayLayout.Bands[0].Columns[“FinishSteps_c”].ValueList = Combo1;

Has a full data regen and IIS reset performed since adding that field? It seems like the column name you are using doesn’t exist - for troubleshooting I’d maybe try:

foreach(var col in myGridList.DisplayLayout.Bands[0].Columns)
{
  MessageBox.Show(col.Name); 
}

This way you can at least see what the col name is being set as. It doesn’t solve the problem, just gets us more info to process

A data regen was performed by the SaaS team (I’m not sure about IIS as the server is managed by Epicor) and all tables and data models are in sync. When I try your suggested code I receive this error:

Error Detail

Message: Exception has been thrown by the target of an invocation.
Inner Exception Message: Object reference not set to an instance of an object.

I updated the code a little to resolve the exception:

EpiUltraGrid myGridList = new EpiUltraGrid();

foreach (var column in myGridList.DisplayLayout.Bands[0].Columns)
{
MessageBox.Show(column.Header.ToString());
}

When I launch the customization I receive a ton of blank message boxes in succession. Now might be a good time to mention that I’m a C# newbie. ><

I see - I think the issue may be the order of operations then. If you are trying to run your code before the grid has been populated by a dataset, it will not contain header names.

What actually populates your grid? a baq? code?

Perhaps you could use the event that fires when the grids datasource changes like:

myGridList.DataSourceChanged += (sender, args) =>
                    {
                                myGridList.DisplayLayout.Bands[0].Columns[“FinishSteps_c”].ValueList = Combo1;
                    };

This would make your change every time the datasource changes. You can place that code in the initializer.

1 Like

You are correct. Running code on form load with no data available returns a whole lot of nothing.

I believe that I have it working correctly now. I used the Form Event Wizard to add an AfterAdapterMethod handler and changed the method name in the Case statement to “GetRows”. I then moved my original code below the Case and am now seeing the intended results. However, I’ve run into a new issue now that has me stumped.

Here is the relevant code I added to through the Event Wizard:

	private void oTrans_adapter_AfterAdapterMethod(object sender, AfterAdapterMethodArgs args)
{
	// ** Argument Properties and Uses **
	// ** args.MethodName **
	// ** Add Event Handler Code **

	// ** Use MessageBox to find adapter method name

            //EpiMessageBox.Show(args.MethodName);
	
	switch (args.MethodName)
	{
	
        case "GetaNewUD01":		
        case "GetRows":
		
			myGridList = (EpiUltraGrid)csm.GetNativeControlReference("7908565c-cc3c-43d1-b85b-9921ad88fb89");
			myGridList.DisplayLayout.Bands[0].Columns["FinishSteps_c"].ValueList = Combo1;

		break;
	}
}

I added the case “GetaNewUD01”: to handle new record creation (in case the user doesn’t search for records first), but for some reason this method isn’t working. I tried using the EpiMessageBox.Show, but it doesn’t display the method when I create a new record. I ran a trace and was able to verify that the method is being used though. Any ideas?

So with GetaNewUDxx, a new record (row) is entered into yourAdapter.UD01.UD01Data.

If you want to make changes before committing you can do so. Ultimately you need to make sure you commit the change by calling yourAdapter.Update().

Also note that calling any other adapter method that will overwrite the internal UD01 before committing it will cause you to lose your data.

And after writing all that, I re-read the question to realize I misunderstood. Let me try again.

The best advice I can give is to uncomment the line in the code that shows the MethodName being called. This way you can confirm the naming. It will be messy as hell with a ton a popups but once you confirm the MethodName you can remove it.

If you don’t see the expected method on create, well… Let’s cross that bridge if we reach it.

I uncommented the line and ran the customization, but when I clicked New to create a record I didn’t receive a message box. I tried saving and deleting the record, both of which resulted in a message box displaying the correct methods (update, delete) so I know that the code is working.

Ok, that must mean that isn’t the same adapter being used to create the record.

We could try to attack this a different way. Is there an EpiDataView on the form related to UD01? If so,

myDataView.ListChanged += (sender, args) =>
            {
                if (args.ListChangedType == ListChangedType.ItemAdded)
                {
                     //do something with your grid
                    //  (sender as EpiDataView).Table.Rows[args.NewIndex]["Key1"] = "YourKey1"; //example changing a value
                    
                }
            }
1 Like

I added a ListChanged event through the form event wizard and used this code for the event handler:

if (args.ListChangedType == ListChangedType.ItemAdded)
    {
		myGridList = (EpiUltraGrid)csm.GetNativeControlReference("7908565c-cc3c-43d1-b85b-9921ad88fb89");
		myGridList.DisplayLayout.Bands[0].Columns["FinishSteps_c"].ValueList = Combo1;
    }

Everything works as intended. I now have a drop down list available when a search is performed and when a new record is added to the table. Thank you very much for your help. I really appreciate it.

1 Like

My pleasure. Thanks for marking the solution!

Could you explain your last code line specifically what is “Combo1”?

Combo1 is the name I gave to a combo box that I added to the form. The last line of code defines the fields in the FinishSteps_c column as a ValueList that use the values from Combo1 as the datasource. At least that’s what I believe is happening. :face_with_raised_eyebrow:

Perfect. Thank you. I just tested this code on my system and it worked. I used the Load Event to call a routine.

private void TaskListForm_Load(object sender, EventArgs args)
{
	// Add Event Handler Code
SetGruidCell();
}

private void SetGruidCell()
{
	EpiUltraGrid myGridList = new EpiUltraGrid();
try
{
//	if (args.ListChangedType == ListChangedType.ItemAdded)

	MessageBox.Show("TEST".ToString());
	myGridList = (EpiUltraGrid)csm.GetNativeControlReference("7d6e33c1-2a19-4722-afbf-f97eb343d1da");
									 
	myGridList.DisplayLayout.Bands[0].Columns["rsiSchedCode_c"].ValueList = rsiSchedCode_txt;
}

	catch( Exception es)
	{
		    // MGA - EAA - Keep commented for future error details reporting 
            // 10/2/2017
			MessageBox.Show(es.Message);
    }

Mazin

}

You can create your own lists as well:

// Create a value list with the key of VL1.
	ValueList valueList = this.ultraGrid1.DisplayLayout.ValueLists.Add( "VL1" );
	
	// Add some items to it. Here the items added have numeric data values and
	// associated display texts. What the user sees in the cells is the display 
	// text for these underlying numeric data value. Also when the user modifies
	// a cell and selects one of the item, what goes in the data source is the
	// associated numeric value.
	valueList.ValueListItems.Add( 1, "One" );
	valueList.ValueListItems.Add( 2, "Two" );
	valueList.ValueListItems.Add( 3, "Three" );
	valueList.ValueListItems.Add( 4, "Four" );
	valueList.ValueListItems.Add( 5, "Five" );

I think you want MessageBox.Show(column.Key); to show the field name used in the column.