Something that I’d find super useful in the near future would be to populate a combo box’s list items programatically. I’ve been through some internet searching and supporting library docs, but haven’t discovered the secret incantations that Epicor is using to populate the drop down lists. Am I missing something?
Hi John,
Below is an example of how I do it. I want the dropdown to be populated with a list of numbers at 75mm increments. The highest number is dependant on the product dimensions being used by the method called Heights;
string opListItems = "";
string ipProduct = Inputs.cmbProduct.Value;
string ipCore = Inputs.cmbCore.Value;
string ipLength = Inputs.cmbLength.Value;
string ipHeight = Inputs.cmbHeight.Value;
if (ipLength == "")
{
ipLength = "0";
}
else
{
int length = System.Convert.ToInt32(ipLength);
if (ipHeight == "")
{
ipHeight = "0";
}
int height = System.Convert.ToInt32(ipHeight);
//MessageBox.Show(length.ToString());
int i = 1;
int j = length - 75;
if (length > 600)
{
j = 600;
}
do
{
opListItems += j.ToString() + "~";
i = i + 1;
j = j - 75;
}
while (j > 75);
}
return opListItems;
I then call this method from the dynamic list entry as below;
Hope this helps
Best regards
Adrian
In my never-ending quest to make code more readable and more efficient, i took this opportunity to optimize your code (please take no offence). One of the big slow-downs in Configurator can be inefficient code in Combo Boxes, and while your code probably is not super critical, it does make some mistakes.
Thinks that I found wrong:
- unused variables declared: This reserves memory that is unnecessary. Every time you declare a variable, it must later be disposed. Combo box code can be called MANY times, thereby these variables are re-declared over and over again. I also converted some of the if blocks into single line if assignments which makes the code more concise.
- appending a string to a string over and over again… this is inefficient because each time you add onto a string, it consumes the memory space one more time. example, if you run this one line of code MyString += “A” 100 times, you might think you only have one string that is 100 characters long… but in reality, you have consumed 5050 bytes of memory, and disposed of 99 variable spots in memory. INSTEAD, you can use “StringBuilder” to make this more efficient. (more about Stringbuilder here)
- Changed the while loop into a for loop which again reduces the number of lines of code.
Here is the result… of course, this is NOT TESTED, so I may have made a typo… but I think you will see that it is not as scary, and should run more efficient.
StringBuilder opListItems = new StringBuilder();
int length = (Inputs.cmbLength.Value == "") ? 0 : System.Convert.ToInt32(Inputs.cmbLength.Value);
if (length != 0) {
for ( int j = (length > 600) ? 600 : length - 75; j > 75; j-=75) {
opListItems.Append( j.ToString() + "~");
}
}
return opListItems.ToString();
Thanks Adrian! I think my question was more vague than it should have been. I’m more hoping to work directly with those combbobox list references, since user defined methods won’t pass around anything less primitive than string[]. I want to interact with the object itself that contains the combobox list values. They’re using Infragistics.Win.UltraWinGrid components, which for the configurator use case is kind of like driving nails with an entire toolbox. It would be nice to be able to use the tools inside.
Just be careful about getting too involved with tweaking data at the infragistics level… Once you move to Kinetics, you will need to re-do things.
Thank you Tim for taking time to show me how to do this more efficiently. I welcome all the help and advice I receive here, especially from someone like yourself, who I know has vast experience with configurators. I have not come across StringBuilder before but there are probably many areas in my configurators where I should have used it. I also appreciate the you pointing out the issue with the unused variables. I leaned a lot from your response and I will be implementing your example first thing on Monday. Thanks again.
I remember when local variables were held in the stack. And a simple POP instruction (or incrementing the stack pointer) was all that was needed.
Edit
And one real question on tilde delimited strings. Should they end with a tilde? Or does that imply a null string at the end of the list?
Does "1st~~3rd~4th~"
equate to
"1st", "", "3rd", "4th", ""
Or
"1st", "", "3rd", "4th"
With the first on having a blank entry at the end.
no, they should not end with a tilde… that would result in "1st", "", "3rd", "4th", ""
One solution is to do the following change to the above:
return opListItems.ToString().TrimEnd('~');
which will trim off the tildes from the end.
That’s where String.Join fits in. Also, when making a sequence of numbers, Enumerable.Range is preferred. We could even lambda the whole thing together now that we’re playing with a Collection type, stuff it inside a String.Join, and only write one line:
return String.Join("~", Enumerable.Range(1, 600/75).Select(x => (x * 75).ToString()));
But that’s turned into code golf, and code golf has no place in enterprise code someone’s going to have to maintain later. If that snippet crossed my radar at work, I’d have it converted to something actually readable, like:
int max = 600;
int increment = 75;
// generate the series of numbers
IEnumerable<int> series = Enumerable.Range(1, max / increment);
// multiply to get the output progression
series = series.Select(x => x * increment);
// concatenate the series of numbers
return String.Join("~", series.Select(x => x.ToString()));