When a value occurs twice in a dropdown, but with different casing, it is impossible to select the second one by typing the value. The UltraCombo will always select the first one - regardless of the case.Here's an example (Windows Forms, C#, .NET 4.x):
public class Form1 : Form { public Form1() { InitializeComponent(); ultraCombo.DataSource = GetDataTable(); } private static DataTable GetDataTable() { var dataTable = new DataTable(); dataTable.Columns.Add("Code", typeof(string)); dataTable.Columns.Add("Description", typeof(string)); dataTable.Rows.Add("a", "lowercase"); // Selectable with a or A dataTable.Rows.Add("B", "UPPERCASE"); // Selectable with b or B dataTable.Rows.Add("c", "lowercase"); // Selectable with c... or C dataTable.Rows.Add("C", "UPPERCASE"); // Cannot select with keyboard return dataTable; } private void UltraCombo_RowSelected(object sender, Infragistics.Win.UltraWinGrid.RowSelectedEventArgs e) { selectedLabel.Text = e.Row != null ? $@"{e.Row.Cells["Code"].Value} {e.Row.Cells["Description"].Value}" : null; } private void InitializeComponent() { this.ultraCombo = new Infragistics.Win.UltraWinGrid.UltraCombo(); this.selectedLabel = new System.Windows.Forms.Label(); ((System.ComponentModel.ISupportInitialize)(this.ultraCombo)).BeginInit(); this.SuspendLayout(); // // ultraCombo // this.ultraCombo.AutoCompleteMode = Infragistics.Win.AutoCompleteMode.None; this.ultraCombo.CharacterCasing = System.Windows.Forms.CharacterCasing.Normal; this.ultraCombo.Location = new System.Drawing.Point(8, 8); this.ultraCombo.Name = "ultraCombo"; this.ultraCombo.RowSelected += new Infragistics.Win.UltraWinGrid.RowSelectedEventHandler(this.UltraCombo_RowSelected); // // selectedLabel // this.selectedLabel.Location = new System.Drawing.Point(8, 40); this.selectedLabel.Name = "selectedLabel"; // // Form1 // this.Controls.Add(this.ultraCombo); this.Controls.Add(this.selectedLabel); this.Name = "Form1"; this.Text = "UltraCombo"; ((System.ComponentModel.ISupportInitialize)(this.ultraCombo)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); } } private Infragistics.Win.UltraWinGrid.UltraCombo ultraCombo; private System.Windows.Forms.Label selectedLabel;
Typing "a" selects the first itemTyping "A" (shift + a) selects the first itemTyping "b" selects the second itemTyping "B" (shift + b) selects the second itemTyping "c" selects the third itemTyping "C" (shift + c) selects... the third item whereas I expected the fourthChanging the order in which c and C get added to the datatable, switches behavior. In that case it's always uppercase C that gets selected regardless typing "c" or "C"The a-A and b-B cases are understandable and probably convenient for the user. The c-C case is wrong in my opinion. The UltraCombo should only try to select the first best match if no exact match was found. Especially because AutoCompleteMode is set to None.
My question: Is there a way to make the UltraCombo properly case-sensitive? It's okay if the a-A and b-B cases become case-sensitive too.I found a topic that discusses exactly the same problem:UltraCombo is ignoring case when selecting values (6 years ago)Sadly the posted solution does not work for me. AutoCompleteMode is already None, CharacterCasing is Normal and adding "dataTable.CaseSensitive = true" to the example above makes no change.
Small update to the example: If you can't see the label add following line:
this.selectedLabel.AutoSize = true;
Hello,
To achieve case sensitive inputs to the UltraCombo you must set a ValueMember and DisplayMember path
eg.
this.ultraCombo1.ValueMember = "Code"; this.ultraCombo1.DisplayMember = "Description";
Adding these two properties will allow you to select "UPPERCASE" with "C" entry.
That works if you want "Description" to be the DisplayMember but I need "Code" to be both ValueMember and DisplayMember... And then it does not work.
The combobox in question in our application contains user-defined data and the description is an optional field that may be empty. The primary data is the code.
The combobox is used to select result codes. Users know most of the codes by heart and only need the dropdown list for the rare cases. Therefore it's important they can reliably enter the codes directly by the keyboard. This works fine for most customers but some use the same codes in uppercase and lowercase to indicate differences. We can't simply ask them to stop doing that - they may have been using these codes for years already in other applications.
Is there a way to achieve this with the UltraCombo or do we have to think about alternative approaches?
After researching this with my development team we've concluded that the UltraCombo is not case sensitive.
You can suggest new product ideas for future versions (or vote for existing ones) at <https://www.infragistics.com/community/ideas>. Submitting your idea will allow you to communicate directly with our product management team, track the progress of your idea at any time, see how many votes it got, read comments from other developers in the community, and see if someone from the product team has additional questions for you. Remember when submitting your idea to explain the context in which a feature would be used and why it is needed as well as anything that would prevent you from accomplishing this today. You can even add screenshots to build a stronger case. Remember that for your suggestion to be successful, you need other members of the community to vote for it. You can also link back to this thread for additional details.
Let me know if you have any questions.
That's unfortunate.
However I think I may have found a workaround. It's not pretty, it has some issues, it probably only applies to our particular case,... but it seems to work.
public Form1() { InitializeComponent(); ultraCombo.DataSource = GetDataTable(); ultraCombo.ValueMember = "Code"; ultraCombo.DisplayMember = "Display"; } private static DataTable GetDataTable() { var dataTable = new DataTable(); dataTable.Columns.Add("Code", typeof(string)); dataTable.Columns.Add("Display", typeof(string)); dataTable.Columns.Add("Description", typeof(string)); dataTable.Rows.Add("a", "a ", "lowercase"); // Selectable with a or A dataTable.Rows.Add("B", "B ", "UPPERCASE"); // Selectable with b or B dataTable.Rows.Add("c", "c ", "lowercase"); // Selectable with c dataTable.Rows.Add("C", "C ", "UPPERCASE"); // Selectable with C return dataTable; }
What I've done is inserting a new column "Display" for the DisplayMember that is identical to the original "Code" column except each value is followed by a space. This space ensures the UltraCombo does not automatically select the list item when typing the code (AutoComplete is set to None).
The drawback is that the RowSelected/ValueChanged events are no longer fired automatically when typing a code that is in the list (you either have to type the extra space or leave the control). Another problem is that if for example codes "d" and "D D" exist, it's once again impossible to type the second because it contains a space and matches with "d " before you can type the second "D".
It is however relatively easy to fix this with some custom code in the TextChanged event:
private void UltraCombo_TextChanged(object sender, EventArgs e) { var row = GetBestMatchInUltraCombo(); if (row != null) selectedTextBox.Text = $@"{row["Code"]} {row["Description"]}"; else selectedTextBox.Clear(); } private void UltraCombo_Leave(object sender, EventArgs e) { UpdateUltraCombo(); } private DataRow GetBestMatchInUltraCombo() { var text = ultraCombo.Text; if (string.IsNullOrWhiteSpace(text)) return null; var dataTable = ultraCombo.DataSource as DataTable; if (dataTable == null) return null; // Trim trailing space(s) and protect against single // quotes for Select() below text = text.Replace("'", "''").TrimEnd(); // Select all rows that match text (not case sensitive) var filteredDataRows = dataTable.Select($"Code = '{text}'"); // If a row matches exactly (case sensitive) return it, // otherwhise return first best match if (filteredDataRows.Length > 1) { var row = filteredDataRows.FirstOrDefault(r => r["Code"].ToString() == text); return row ?? filteredDataRows[0]; } if (filteredDataRows.Length == 1) return filteredDataRows[0]; return null; } private void UpdateUltraCombo() { var row = GetBestMatchInUltraCombo(); if (row == null) return; ultraCombo.Value = row["Code"]; }
This is just some quick and dirty code to make the sample work. It'll probably need more spit and polish but I think this workaround is usable for our case.
So... just in case you are interested or run into future issues, I thought you might like to know WHY this code works...Basically, what happens in this case is that you type in a string and the combo tries to find a matching string in the DisplayText column. Since your DisplayText values contain an extra space, it does not find a match. Ordinarily, the combo would find a match on the DisplayText list, and then it's Value would return the DataValue from the matching item? But what does the combo do for the Value when there is no matching DisplayText? The only thing it can do is return the actual text you typed in - ignoring the DisplayText. The Value is, of course, an exact match - it is essentially case sensitive.
So that's why this works. You are essentially setting it up in such a way that the DisplayText will NEVER match. Unless, of course, the user happens to type in a matching text with a space at the end.
Other than that one caveat (which seems unlikely to occur), I can't immediately thing of anything wrong with this solution. It's relying on some weird and esoteric behavior, but that behavior has been that way forever and it's unlikely to change.
Thank you for the explanation, Mike!
So far we have not found major issues with the workaround. It has some weird (but expected) behavior when following data is present:
dataTable.Rows.Add("d", "d ", "lowercase"); dataTable.Rows.Add("D D", "D D ", "UPPERCASE");
Typing <D> <space> <D> to get the second item actually results into "d D" being displayed because once you typed <D> <space> the UltraCombo automatically selects item "d " and updates the displayed text. Despite that it does not break functionality. After completing the entry with the second <D>, the new code in the TextChanged event will find the best match ("D D") and use that. At that moment the displayed text is still wrong but after leaving the UltraCombo the Leave event will update the Value property with the best match. Then the displayed text updates to "D D ". Perfect.
There are obviously scenarios that do not work:
dataTable.Rows.Add("d", "d ", "lowercase"); dataTable.Rows.Add("d D", "d D ", "mixed case"); dataTable.Rows.Add("D D", "D D ", "UPPERCASE");
It is now impossible to select the last entry by typing <D> <space> <D> because the behavior described above forces the first uppercase "D" to lowercase "d" and hence you'll always end up with the second item "d D".
This is not really a problem for us. The data in this particular UltraCombo will rarely, if ever, contain spaces so users are unlikely to end up into that scenario.
Yeah, that makes sense. If you have duplicate DisplayText - or in this case duplicates that only differ by case (which is ignored), then it will always end up picking the first one when typing.
The combo should handle it correctly if you were to drop down the list and select "D D", though.