DropDownList custom autocomplete

8 posts, 1 answers
  1. Aleksandr
    Aleksandr avatar
    7 posts
    Member since:
    Nov 2012

    Posted 10 Jun 2014 Link to this post

    Hello!
    I'm using RadDropDownList control in DropDown and SuggestAppend mode. I have a databound collection of customers (simple object with properties Id, Name, Phone, Email etc).

    I've figured out how to implement "contains" search with:
    ddlCustomers.DropDownListElement.AutoCompleteSuggest.SuggestMode = SuggestMode.Contains;

    But now I need to search not only by customer Name, but by Phone too (and maybe by Email in the future).
    I think that I need to implement my own suggest helper and inherit it from AutoCompleteSuggestHelper.
    Am I right? If so, which methods should I override? Or maybe there is more simple solution here?
    Thank you in advance.
  2. Answer
    Dess | Tech Support Engineer, Sr.
    Admin
    Dess | Tech Support Engineer, Sr.  avatar
    3903 posts

    Posted 13 Jun 2014 Link to this post

    Hello Aleksandr,

    Thank you for writing.

    Here is a sample implementation of a custom AutoCompleteSuggestHelper. Overriding the DefaultFilter method gives you the option to achieve custom logic for filtering by two or more fields.

    As to the SyncItemsCore method, it is used only to assign the DataBoundItem to the auto-complete item's Tag property, which will be used for access to fields different than the DisplayMember/ValueMember:
    public Form1()
    {
        InitializeComponent();
     
        this.radDropDownList1.DropDownStyle = Telerik.WinControls.RadDropDownStyle.DropDown;
        this.radDropDownList1.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
        this.radDropDownList1.DropDownListElement.AutoCompleteSuggest.SuggestMode = SuggestMode.Contains;
    }
     
    private void Form1_Load(object sender, EventArgs e)
    {
        this.customersTableAdapter.Fill(this.nwindDataSet.Customers);
        this.radDropDownList1.DataSource = this.customersBindingSource;
        this.radDropDownList1.DisplayMember = "ContactName";
        this.radDropDownList1.ValueMember = "CustomerID";
    }
     
    public class CustomDropDownList : RadDropDownList
    {
        public override string ThemeClassName 
        {
            get
            {
                return typeof(RadDropDownList).FullName; 
            }
        }
     
        protected override RadDropDownListElement CreateDropDownListElement()
        {
            return new CustomDropDownListElement();
        }
    }
     
    public class CustomDropDownListElement : RadDropDownListElement
    {
        protected override Type ThemeEffectiveType    
        {
            get   
            {
                return typeof(RadDropDownListElement);    
            }
        }
     
        protected override AutoCompleteSuggestHelper CreateAutoCompleteSuggestHelper()
        {
            return new CustomAutoCompleteSuggestHelper(this);
        }
    }
     
    public class CustomAutoCompleteSuggestHelper : AutoCompleteSuggestHelper
    {
        public CustomAutoCompleteSuggestHelper(RadDropDownListElement owner) : base(owner)
        {
        }
     
        protected override bool DefaultFilter(RadListDataItem item)
        {
            DataRowView rowView = item.Tag as DataRowView;
            if (rowView != null)
            {
                DataRow curtomerRow = rowView.Row;
                string customerAdrress = curtomerRow["Address"].ToString();
                return item.Text.ToLower().StartsWith(this.Filter.ToLower()) &&
                       customerAdrress.ToLower().Contains(this.Filter.ToLower());
            }
     
            return base.DefaultFilter(item);
        }
     
        protected override void SyncItemsCore()
        {
            this.DropDownList.ListElement.Items.Clear();
            this.DropDownList.ListElement.BeginUpdate();
            foreach (RadListDataItem item in Owner.Items)
            {
                RadListDataItem newItem = new RadListDataItem(item.Text);
                newItem.Tag = item;
                newItem.Value = item.Value;
                newItem.TextWrap = item.TextWrap;
                newItem.Enabled = item.Enabled;
                newItem.Tag = item.DataBoundItem;
                this.DropDownList.ListElement.Items.Add(newItem);
            }
     
            this.DropDownList.ListElement.EndUpdate();
        }
     
        public override void AutoComplete(KeyPressEventArgs e)
        {
            base.AutoComplete(e);
            if (this.DropDownList.Items.Count > 0)
            {
                this.DropDownList.SelectedIndex = this.DropDownList.FindString(this.Filter);
            }
        }
    }

    Note that this is just an example and it may not cover all possible cases. Feel free to modify it on a way, which suits your requirement best.

    I hope this information helps. Should you have further questions, I would be glad to help.

    Regards,
    Desislava
    Telerik
     
    Check out Telerik Analytics, the service which allows developers to discover app usage patterns, analyze user data, log exceptions, solve problems and profile application performance at run time. Watch the videos and start improving your app based on facts, not hunches.
     
  3. Aleksandr
    Aleksandr avatar
    7 posts
    Member since:
    Nov 2012

    Posted 16 Jun 2014 Link to this post

    Thank you! This worked for me.
  4. Fariba
    Fariba avatar
    24 posts
    Member since:
    May 2014

    Posted 16 Jan 2018 Link to this post

    Hi

    I am using a RadDropDownList and bounding the dataSourde .

    DisplayMember is the combination of 2 columns. // DisplayMember= Firstcol+" ["+SecondCol+"]"

    I need the shown datas of  the AutoCompleteSuggestHelper’s pop-up has a special custom filter

    first contains of first column, then contains of the second column (of displaymember)

    So I inherited CustomAutoCompleteSuggestHelper of AutoCompleteSuggestHelper and overide DefaultFilter

    protected override bool DefaultFilter(RadListDataItem item)

            {
                this.DropDownList.SortStyle = Telerik.WinControls.Enumerations.SortStyle.None;

                var newlist = item.Text.Split('[');
                return ((newlist[0].ToLower().Contains(this.Filter.ToLower())) || newlist[1].ToLower().Contains(this.Filter.ToLower()));
                   
            }

    and assigned this class to my dropdown

    mydropdown.DropDownListElement.AutoCompleteSuggest = new CustomAutoCompleteSuggestHelper(cmbInstruments.DropDownListElement);

     

    it works , but the problem is the DropDownList.SortStyle is changed.

    For some reason I want it in none style mode  ,but by raising DefaultFilter it changed to Ascending mode

     

    StackTrace:

    Telerik.WinControls.UI.dll!Telerik.WinControls.UI.AutoCompleteSuggestHelper.ApplyFilterToDropDown(string filter)

     Telerik.WinControls.UI.dll!Telerik.WinControls.UI.RadListElement.SetSortStyle(Telerik.WinControls.Enumerations.SortStyle value)

    Telerik.WinControls.UI.dll!Telerik.WinControls.UI.RadListElement.OnSortStyleChanged(Telerik.WinControls.Enumerations.SortStyle sortStyle) 

     

    What should I do?

  5. Fariba
    Fariba avatar
    24 posts
    Member since:
    May 2014

    Posted 16 Jan 2018 in reply to Dess | Tech Support Engineer, Sr. Link to this post

    Hi
    I am using a RadDropDownList and bounding the dataSourde .
    DisplayMember is the combination of 2 columns. // DisplayMember= Firstcol+" ["+SecondCol+"]"
    I need the shown datas of  the AutoCompleteSuggestHelper’s pop-up has a special custom filter
    first contains of first column, then contains of the second column (of displaymember)
    So I inherited CustomAutoCompleteSuggestHelper of AutoCompleteSuggestHelper and overide DefaultFilter
    protected override bool DefaultFilter(RadListDataItem item)
            {
                this.DropDownList.SortStyle = Telerik.WinControls.Enumerations.SortStyle.None;

                var newlist = item.Text.Split('[');
                return ((newlist[0].ToLower().Contains(this.Filter.ToLower())) || newlist[1].ToLower().Contains(this.Filter.ToLower()));
                   
            }
    and assigned this class to my dropdown
    mydropdown.DropDownListElement.AutoCompleteSuggest = new CustomAutoCompleteSuggestHelper(mydropdown.DropDownListElement);


    it works , but the problem is the DropDownList.SortStyle is changed.
    For some reason I want it in none style mode  ,but by raising DefaultFilter it changed to Ascending mode


    StackTrace:
    AutoCompleteSuggestHelper.ApplyFilterToDropDown(string filter)
    RadListElement.SetSortStyle(Telerik.WinControls.Enumerations.SortStyle value)
    RadListElement.OnSortStyleChanged(Telerik.WinControls.Enumerations.SortStyle sortStyle) 


    What should I do?
  6. Dess | Tech Support Engineer, Sr.
    Admin
    Dess | Tech Support Engineer, Sr.  avatar
    3903 posts

    Posted 18 Jan 2018 Link to this post

    Hello, Fariba,   

    Thank you for writing.  

    By default, the items displayed in the AutoCompleteSuggestHelper’s pop-up are sorted alphabetically. You can manipulate the sort order by using a custom comparer. A sample approach is demonstrated in the Customize auto-complete helpers section in the following help article: https://docs.telerik.com/devtools/winforms/dropdown-listcontrol-and-checkeddropdownlist/dropdownlist/features/auto-complete

    I hope this information helps. Should you have further questions I would be glad to help. 
     
     Regards,
    Dess
    Progress Telerik
    Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
  7. Fariba
    Fariba avatar
    24 posts
    Member since:
    May 2014

    Posted 22 Jan 2018 in reply to Dess | Tech Support Engineer, Sr. Link to this post

    I did as u said and I moved all my code to the Compare method of the CustomComparer

    but now there is another problem and compare method raised all the time for comapring all the items of Data source and it made filtering to slow.

    I try to make condition on filter length by  

      private bool FilterItem(RadListDataItem item)
            {
                if (this.Filter.Length > 2)
                {
                    return true;
                }
                return false;
            } 

    and assign it to the  CustomAutoCompleteSuggestHelper.DropDownList.Filter or raddropdownlist.filter.

    But it does not work.

    ApplyFilterToDropDown raised and by setting

    this.DropDownList.ListElement.DataLayer.DataView.Comparer = new CustomCompare 

    compare method raised all the time.

    Is there any way to raised compare method by condition for example while the filter text length is more than 2 character .

     

     

     

    Thanks 

    Fariba

  8. Dess | Tech Support Engineer, Sr.
    Admin
    Dess | Tech Support Engineer, Sr.  avatar
    3903 posts

    Posted 23 Jan 2018 Link to this post

    Hello, Fariba,  

    Thank you for writing back. 

    It is normal that the custom comparer is called many times. With each action that needs to display the items it is required to order these items and then the comparer is used. Try to optimize the comparer. In the AutoCompleteSuggestHelper you can override the HandleAutoSuggest method and don't call the basic logic if you have less than 2 characters entered in the text box.

    If you are still experiencing any further difficulties, feel free to submit a support ticket where you can provide a sampel project demonstrating the problem. Thus, our support staff will gladly assist you. 

    I hope this information helps. If you have any additional questions, please let me know. 

     Regards,
    Dess
    Progress Telerik
    Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
Back to Top