This is a migrated thread and some comments may be shown as answers.

Optimizing GridViewComboBoxColumn

3 Answers 102 Views
GridView
This is a migrated thread and some comments may be shown as answers.
Joemelle
Top achievements
Rank 1
Joemelle asked on 28 Aug 2013, 02:12 PM
Hi,

I have a RadGridView that has a GridViewComboBoxColumn containing 40,000+ values through data binding. Viewing the combobox values in every cell under that column is taking a few seconds. I think the reason for this sluggishness is because it loads up the values only when a cell is clicked. So I'm wondering if there's any way to optimize this behavior. 

Thanks!

3 Answers, 1 is accepted

Sort by
0
George
Telerik team
answered on 02 Sep 2013, 01:12 PM
Hi Joemelle,

Thank you for contacting us.

You can implement a custom solution which will fit your needs. I have created a sample class which may get you started: 
public class MyGridViewComboBoxColumn : GridViewComboBoxColumn
{
    private IList dynamicDataSource;
    private IList actualDataSource;
    private int dataLoadStep = 100;
    private RadDropDownListEditor comboBoxEditor;
    private RadDropDownListElement editorElement;
    private int savedScrollPosition;
 
    public int DataLoadStep
    {
        get
        {
            return this.dataLoadStep;
        }
        set
        {
            if (value < 50)
            {
                throw new ArgumentException("The DataLoadStep can not be less than 50 so that a scrollbar can be visible after the initial load");
            }
 
            this.dataLoadStep = value;
        }
    }
 
    public IList ActualDataSource
    {
        get
        {
            return this.actualDataSource;
        }
        set
        {
             
            this.actualDataSource = value;
            this.DataSource = this.actualDataSource;
        }
    }
 
    public IList DynamicDataSource
    {
        get
        {
            return this.dynamicDataSource;
        }
        set
        {
            if (this.actualDataSource == null)
            {
                throw new ArgumentException("Add a ActualDataSource first");
            }
 
            this.dynamicDataSource = value;
            IList dataSource = (IList)this.DataSource;
            for (int i = dataSource.Count; i < this.DataLoadStep; i++)
            {
                dataSource.Add(this.dynamicDataSource[i]);
            }
             
        }
    }
 
    public MyGridViewComboBoxColumn(int dataLoadStep)
        :this()
    {
        this.DataLoadStep = dataLoadStep;
    }
 
    public MyGridViewComboBoxColumn()
        :base()
    {
    }
 
    public override void InitializeEditor(IInputEditor editor)
    {
        base.InitializeEditor(editor);
 
        RadDropDownListEditor comboBoxEditor = editor as RadDropDownListEditor;
        if (comboBoxEditor != null)
        {
            this.comboBoxEditor = comboBoxEditor;
            RadDropDownListElement element = (RadDropDownListElement)comboBoxEditor.EditorElement;
            if (element != null)
            {
                this.editorElement = element;
                element.ListElement.VScrollBar.ValueChanged -= VScrollBar_ValueChanged;
                element.ListElement.VScrollBar.ValueChanged += VScrollBar_ValueChanged;
            }
        }
    }
 
    private void VScrollBar_ValueChanged(object sender, EventArgs e)
    {
        RadScrollBarElement scroll = (RadScrollBarElement)sender;
        if (scroll.Value + scroll.LargeChange >= scroll.Maximum - 400)
        {
            this.savedScrollPosition = scroll.Value;
            this.LoadDataSource();
        }
    }
 
    private void LoadDataSource()
    {
        IList currentDataSource = (IList)this.DataSource;
        int maxCount = currentDataSource.Count + this.dataLoadStep;
        if (maxCount < this.DynamicDataSource.Count)
        {
            for (int i = currentDataSource.Count; i < maxCount; i++)
            {
                object source = this.dynamicDataSource[i];
                this.actualDataSource.Add(source);
            }
 
            this.comboBoxEditor.EndEdit();
            this.InitializeEditor(this.comboBoxEditor);
            this.editorElement.ShowPopup();
            this.editorElement.ListElement.VScrollBar.Value = this.savedScrollPosition;
        }
    }
}

You can use it as follows:
MyGridViewComboBoxColumn comboCol = new MyGridViewComboBoxColumn();
this.grid.Columns.Insert(0, comboCol);
comboCol.DisplayMember = "Name";
comboCol.ActualDataSource = new List<BindingClass>();
comboCol.DynamicDataSource = this.bindingCollection;

My BindingClass has a single Property - "Name" and the bindlingCollection is a List<BindingClass>.

I hope this helps.

Regards,
George
Telerik
TRY TELERIK'S NEWEST PRODUCT - EQATEC APPLICATION ANALYTICS for WINFORMS.
Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
Sign up for Free application insights >>
0
Joemelle
Top achievements
Rank 1
answered on 04 Sep 2013, 11:02 AM
Thanks for your response. I have tried the code and I think the only downside to this is that if the AutoCompleteMode is set to SuggestAppend wherein if the last item was typed and the combobox has not been scrolled down up to the last item, it would not be autocompleted. Am I right? Or did I just missed a code to fit my requirement?

Thanks!
0
George
Telerik team
answered on 09 Sep 2013, 09:54 AM
Hello Joemelle,

Thank you for writing back.

That is correct. The combo box column is loading the items from the data source on demand. You can implement your own AutoComplete by searching the ActualDataSource using a CurrencyManager. A simple example would look like this:
public override void InitializeEditor(IInputEditor editor)
{
    base.InitializeEditor(editor);
 
    RadDropDownListEditor comboBoxEditor = editor as RadDropDownListEditor;
    if (comboBoxEditor != null)
    {
        this.comboBoxEditor = comboBoxEditor;
        RadDropDownListElement element = (RadDropDownListElement)comboBoxEditor.EditorElement;
        if (element != null)
        {
            this.editorElement = element;
            element.ListElement.VScrollBar.ValueChanged -= VScrollBar_ValueChanged;
            element.ListElement.VScrollBar.ValueChanged += VScrollBar_ValueChanged;
 
            ((RadDropDownListEditorElement)element.EditorElement).EditableElement.TextBox.KeyPress += TextBox_KeyPress;
            ((RadDropDownListEditorElement)element.EditorElement).EditableElement.TextBox.KeyPress += TextBox_KeyPress;
        }
    }
}
 
void TextBox_KeyPress(object sender, KeyPressEventArgs e)
{
    if (char.IsDigit(e.KeyChar) || char.IsLetter(e.KeyChar))
    {
        CurrencyManager manager = this.OwnerTemplate.BindingContext[this.ActualDataSource] as CurrencyManager;
        if (manager != null)
        {
            this.editorElement.BeginUpdate();
            PropertyDescriptorCollection descriptors = manager.GetItemProperties();
            PropertyDescriptor descriptor = descriptors.Find(this.DisplayMember, true);
            RadDropDownListEditorElement editor = sender as RadDropDownListEditorElement;
             
            for (int i = 0; i < this.ActualDataSource.Count; i++)
            {
                manager.Position = i;
                string value = (string)descriptor.GetValue(this.actualDataSource[i]);
                //do some autoCompleteLogic
            }
 
            this.editorElement.EndUpdate();
        }
    }
}

I hope this helps.

Regards,
George
Telerik
TRY TELERIK'S NEWEST PRODUCT - EQATEC APPLICATION ANALYTICS for WINFORMS.
Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
Sign up for Free application insights >>
Tags
GridView
Asked by
Joemelle
Top achievements
Rank 1
Answers by
George
Telerik team
Joemelle
Top achievements
Rank 1
Share this question
or