My goal is to have a multi column combo box such that the list changes as the user types in the combo box (by hitting an API) and then when the user clicks one of the items in the drop down I'd like to show the value from one of the columns. I've gotten the first part working but the issue arises when the user clicks on an item.
With the code below what I'm observing is that when the user types in the combo box, the ValueChanged handler fires and gets sent the text the user has typed which allows me to call the API with that value. The drop down displays the data as I expect. So far so good. Then when the user clicks on an item in the drop down, the ValueChanged handler fires not with the text but with the Id from my model since the ValueField is set to the Id. But I'm also getting an invalid cast error in the browser console. If I change the ValueField to a string, say OrderNumber, the ValueChanged and OnChange handlers fire with the OrderNumber value and I no longer get the error, but the problem is that OrderNumber is not unique so I can't find the distinct item in the collection. So the question is, how do I send the typed text into the ValueChanged handler and send the Id into the OnChange handler? Thanks in advance for your help.
<TelerikMultiColumnComboBox Data="_orders"
AllowCustom="true"
Value="_selectedOrder"
ValueExpression="(() => _selectedOrder)"
ValueChanged="@(async (string order) => await OrderValueChangedAsync(order))"
OnChange="OrderChangedHandler"
ValueField="@nameof(OrderDto.Id)"
TextField="@nameof(OrderDto.OrderNumber)">
<MultiColumnComboBoxColumns>
<MultiColumnComboBoxColumn Field="@nameof(OrderDto.Source)" Title="Source"></MultiColumnComboBoxColumn>
<MultiColumnComboBoxColumn Field="@nameof(OrderDto.DeliverOn)" Title="Deliver On"></MultiColumnComboBoxColumn>
<MultiColumnComboBoxColumn Field="@nameof(OrderDto.OrderNumber)" Title="Order Number"></MultiColumnComboBoxColumn>
<MultiColumnComboBoxColumn Field="@nameof(OrderDto.Suffix)" Title="Suffix"></MultiColumnComboBoxColumn>
</MultiColumnComboBoxColumns>
<MultiColumnComboBoxSettings>
<MultiColumnComboBoxPopupSettings Width="600px" />
</MultiColumnComboBoxSettings>
</TelerikMultiColumnComboBox>
private string _selectedOrder;
private async Task OrderValueChangedAsync(string orderNumber)
{
try
{
Console.WriteLine($"ValueChanged fired with value {orderNumber}");
if (orderNumber == null || orderNumber.Length < 5)
{
_orders = new(); // Don't load orders until the user has typed in at least 4 characters so we don't bring back too many orders
return;
}
if (_activity.Type == "C")
{
_orders = await APIService.CallAPIAsync<List<OrderDto>>($"RMOActivity/GetSalesOrders?orgCode={AppState.SelectedDivision.OrgCode}&orderNumber={orderNumber}", null, HttpMethod.Get);
}
else
{
_orders = await APIService.CallAPIAsync<List<OrderDto>>($"RMOActivity/GetPurchaseOrders?orgCode={AppState.SelectedDivision.OrgCode}&purchaseOrderNumber={orderNumber}", null, HttpMethod.Get);
}
}
catch (Exception e)
{
LogError("Error loading orders", e);
}
finally
{
Console.WriteLine($"ValueChanged finished with value {orderNumber}");
}
}
private void OrderChangedHandler(object order)
{
try
{
Console.WriteLine($"OnChange fired with value {(order == null ? "null" : order.ToString())}");
if (order != null)
{
_selectedOrder = (string)order;
}
Console.WriteLine($"OnChange finished with value {(order == null ? "null" : order.ToString())}");
}
catch (Exception e)
{
LogError("Error loading order", e);
}
}
public class OrderDto
{
public int Id { get; set; }
public string Source { get; set; }
public DateOnly? DeliverOn { get; set; }
public string OrderNumber { get; set; }
public string Suffix { get; set; }
public string CustomerOrVendorNumber { get; set; }
public string ShipToOrVendorCode { get; set; }
}