The data in all of our multi column combo boxes has a key value always as the first column in the grid. We want our users to be able to enter one of those key values then hit tab to select it. However, in some cases, just entering the key value doesn't cause the record with that key value to be at the top, so when the user hits tab it selects the top record instead of the record matching the key value entered.
See example below with US states as values:
In scenarios like these, I'd like to be able override the default selection logic and see if there is a record where the text in the search box exactly matches a key value, if so, select that value instead of the first value.
This was the last thing I tried inside the PreviewKeyDown event but it seemed to freeze and then not work as expected.
if (e.Key == System.Windows.Input.Key.Tab)
{
string typedText = MultiColumnComboBox
.FindChildByType<TextBox>()
.Text
.Trim();
if (MultiColumnComboBox.DropDownContentManager.DropDownElement is RadGridView gridView)
{
string keyFieldName = gridView.Columns[0].UniqueName;
var itemToSelect = gridView.Items
.OfType<DataRow>()
.FirstOrDefault(row =>
{
var keyValue = row[keyFieldName];
return keyValue != null &&
keyValue.ToString().Equals(typedText, StringComparison.OrdinalIgnoreCase);
});
if (itemToSelect != null)
{
gridView.SelectedItem = itemToSelect;
}
}
}
I've tested your code and it doesn't freeze on my side, but indeed it doesn't work as intended. To fix this should delay the selection a bit.
private void RadMultiColumnComboBox_PreviewKeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.Tab) { var mccb = (RadMultiColumnComboBox)sender; var text = mccb.AutoCompleteProvider.SearchText; var dt = (DataTable)mccb.ItemsSourceProvider.ItemsSource; var itemToSelect = dt.Rows.OfType<DataRow>() .FirstOrDefault(row => row["Id"] != null && row["Id"].ToString().Equals(text, StringComparison.OrdinalIgnoreCase)); if (itemToSelect != null) { Dispatcher.BeginInvoke(new Action(() => { mccb.SetCurrentValue(RadMultiColumnComboBox.SelectedItemProperty, itemToSelect); })); } } }
You can see this in the attached project. I hope it helps.
It's half working now. As is, every time the user hits tab it runs that code, which means the user can never tab out of the field. So, if I make it so it only executes if the MultiColumnComboBox.SelectedItem is null, then it does override the selection and set the proper selected item the first time the user hits tab. But the second time the user hits tab (to attempt to leave the field it re-selects the first item in the grid again instead of moving to the next field.
To resolve this, you can extend the solution a bit and empty the CurrentItem of the associated RadGridView when the search text is empty. This will prevent part of the internal logic of RadMultiColumnComboBox from executing.
private void RadMultiColumnComboBox_PreviewKeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.Tab) { var mccb = (RadMultiColumnComboBox)sender; var text = mccb.AutoCompleteProvider.SearchText; if (!string.IsNullOrEmpty(text)) { // the custom selection logic here } else { var gridView = (RadGridView)mccb.DropDownContentManager.DropDownElement; gridView.CurrentItem = null; } } }