Hi,
The problem is that your ID field is of type 'nullable long'.
If you choose an item from the list, then your combo is converted the text into a long. In that case, there's no problem.
If you type something that is not on the list, the combo returns the text you typed. Since that text cannot be converted into a long, there are exceptions being raised and caught by the editor. You don't see the exceptions, because they are caught, but they still slow down execution.
Frankly, the way you have this set up doesn't really make sense. The user can type into the cell, but there's no way what they type can possibly be saved to the data source, so there's really no point in it. It can only cause confusion.
Typically, in a case like this where the field in the grid cannot accept an invalid (string) value, you would set the column's Style to DropDownList. This would force the user to choose an item from the list and disallow typing. You could add a null option to your list, also, if you like.
No, using tables is not really appropriate. We Code First Entity Framework 6 and directly bind to the POCO classes utilising a customised BindingList to provide the child records which then handles the additions / removals from the parent etc. Using the POCO classes allows us to build in logic, and implement IDataErrorInfo which works well with the grid. The grid works fantastically well in this scenario, except for the combo box lag. Binding the grid directly to the Binding list has the same issue.
Sample Binding List we use (T is the child entity, while P is the parent entity). The child entity implements IDataErrorInfo which is wingrid understands. Translating this to a datatable doesn't work well as then we lose the POCO capabilities on the fields, real time calculation fields and so on which we like to keep in the POCO class for calculating the row totals, tax, and so on.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using oneFlowProLib.Interfaces;
using System.Data.Entity;
namespace oneFlowProLib.Data
{
public class DetailItemBindableList<T, P> : BindingList<T>
where T : IDetailItem
where P : IBindableDetails<T>
private P myParent;
internal DetailItemBindableList(P parent)
myParent = parent;
foreach (var myItem in myParent.Details)
this.Items.Add(myItem);
}
protected override void RemoveItem(int index)
var myItem = this[index];
if (myItem != null)
myParent.Details.Remove(myItem);
if(myItem.ID>0)
var myContext = myParent.GetContext();
myContext.Set(typeof(T)).Remove(myItem);
base.RemoveItem(index);
public override void CancelNew(int itemIndex)
var myItem = this[itemIndex];
base.CancelNew(itemIndex);
protected override void OnListChanged(ListChangedEventArgs e)
if (myParent == null)
return;
int indexPosition = e.NewIndex;
if (this.Count > e.NewIndex)
var myItem = this[indexPosition];
switch (e.ListChangedType)
case ListChangedType.ItemAdded:
myParent.Details.Add(myItem);
break;
base.OnListChanged(e);
public bool HasErrors()
return this.Any(a => a.HasErrors());
Sample Child entity which is what the grid binds to through the bindinglist
[Table("BankingDetail")]
public class BankingDetail : DataErrorInfo, IDetailItem
public BankingDetail() { }
#region Properties
[Key]
public long ID { get; set; }
[Required]
public long? CategoryID { get; set; }
public long BankingID { get; set; }
[StringLength(255)]
public string Description { get; set; }
public decimal Amount { get; set; }
public decimal TaxRate { get; set; }
public decimal Tax { get { return (Amount * TaxRate).ToRoundedCurrency(4); } private set { } }
public decimal Total { get { return (Amount + Tax).ToRoundedCurrency(); } private set { } }
public decimal RunTotal
get
if (Banking.Type == Banking.BankingTypes.Deposit)
return Total;
else
return Total * -1;
private set { }
[StringLength(100)]
public string TaxCode { get; set; }
public virtual Category Category { get; set; }
public virtual Banking Banking { get; set; }
#endregion
#region Dynamic Properties
#region Methods
public bool Validate()
this.ClearErrors();
if(this.CategoryID==null)
this.SetColumnError("Category", "invalid");
this.Error = "Category Required";
if(string.IsNullOrWhiteSpace(this.Description))
this.SetColumnError("Description", "required");
this.Error = "Description Required";
return !this.HasErrors();
Ideally if there is an override on the ultracomboeditor we can override would be best, to avert the attempted translation, or whatever it is trying to do when the item isn't in the list. Our combo control inherits the ultracomboeditor so we would have no problem overriding something it is doing if that is possible, and prevent the process from happening which causes the lag.
Hello Streven,
Thank you for your feedback.
I have investigated further your issue. I have tried your scenario but instead to BindingSource I have set the UltraGrid’s DataSource to DataTable. In this way UltraComboEditor started to work flawlessly. I have also tried these two scenarios with MS DataGridView. What I found is when DataGridView is bound to BindingSource it works slow and throws many exceptions in the Output window. When DataGridView is bind to DataTable it works flawlessly.
I do believe this issue appears because of the BindingSource and my suggestion is if it is possible to change your DataSource. Please check attached my test sample solution.
Please let me know if you have any further questions.
Thanks Milko,
The problem with using the same value type is then back end binding issues with the entity classes. Will have to make temporary holding fields and such like.
The other issue is cross contamination, say for instance the behind the scenes "Long ID" is 158, but the product code for a product is also 158 but it's behind the scenes value is 190. I guess a not in list check could probably cater for this but it makes things more complicated.
Is it possible not to have the editor cast to the value member type when something is entered that isn't in the list. Simply return null? Maybe an option on the control to allow this. I.E. Cast null to value member when item not in list. That would solve the problem.We typically inherit and build custom controls based on the Infragistics one. Is there an override I can put on the control to do this? I tried overriding the value {get;set;} but that doesn't seem to trigger.
Thank you for posting in our forum.
When you have an UltraGridCell with UltraComboEditor as an editor and enter in the cell a text not presenting in the UltraComboEditor’s items here is what happens:
1. As you set the AutoCompleteMode to SuggestAppend on each keystroke end user enters the editor is trying to find a list item that matches the user input.
2. If the editor does not succeed to find such item it tries to cast the input to the ValueMember type.
3. If casting is unsuccessful the editor throws an exception which is then caught and operated by the grid.
Please note the process of throwing, catching and processing an exception however is slow. This is why you experience this behavior. More about UltraGrid performance you may find by following the next link http://ko.infragistics.com/community/forums/t/15306.aspx
Like a work around you may use a data source where ValueMember and DisplayMember are of same data type. Then steps two and three from above will note happened. More about UltraComboEditor Value property you may find by following the next link http://help.infragistics.com/Help/Doc/WinForms/2014.2/CLR4.0/html/Infragistics4.Win.UltraWinEditors.v14.2~Infragistics.Win.UltraWinEditors.UltraComboEditor~Value.html
Please find attached your revised sample with UltraComboEditor’s ValueMember and DisplayMember both set to type of string.