Optimizing GridViewComboBoxColumn

4 posts, 0 answers
  1. Joemelle
    Joemelle avatar
    2 posts
    Member since:
    Nov 2012

    Posted 28 Aug 2013 Link to this post

    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!
  2. George
    Admin
    George avatar
    500 posts

    Posted 02 Sep 2013 Link to this post

    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 >>
  3. Joemelle
    Joemelle avatar
    2 posts
    Member since:
    Nov 2012

    Posted 04 Sep 2013 Link to this post

    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!
  4. George
    Admin
    George avatar
    500 posts

    Posted 09 Sep 2013 Link to this post

    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 >>
Back to Top