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

AutoCompleteSuggest customised comparer

5 Answers 161 Views
DropDownList
This is a migrated thread and some comments may be shown as answers.
Clive
Top achievements
Rank 1
Clive asked on 17 Nov 2011, 12:33 PM
Hi,

I was wondering if the solution I created below is the best way to do what I want.

I have a list that when the user types in, i'd like the suggestions to pop up, to suggest the items that begin with the text first, but then also include all other items that have that text within it below that.

i.e.
if the list is

aper

aaper

ape

per

pants per

aaa per


and the user types 'p' then I want the list to show

pants per

per

aaa per

aaper

ape

aper


when the user types 'pe' then i want the list to show

per

aaa per

aaper

ape

aper

pants per



when the user types 'per' then i want the list to show

per

aaa per

aaper

aper

pants per


My ApplyFilterToDropDown is an almost copy of the Telerik one, but injecting my comparer instead. I had to do this because if I just set the ItemsSortComparer to mine, then called the base.ApplyFilterToDropDown it always got wiped out, so I resorted to this.

Imports Telerik.WinControls.UI
  
Public Class Form7
    Inherits System.Windows.Forms.Form
  
    'Form overrides dispose to clean up the component list.
    <System.Diagnostics.DebuggerNonUserCode()> _
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        Try
            If disposing AndAlso components IsNot Nothing Then
                components.Dispose()
            End If
        Finally
            MyBase.Dispose(disposing)
        End Try
    End Sub
  
    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer
  
    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    <System.Diagnostics.DebuggerStepThrough()> _
    Private Sub InitializeComponent()
        Dim RadListDataItem1 As Telerik.WinControls.UI.RadListDataItem = New Telerik.WinControls.UI.RadListDataItem()
        Dim RadListDataItem2 As Telerik.WinControls.UI.RadListDataItem = New Telerik.WinControls.UI.RadListDataItem()
        Dim RadListDataItem3 As Telerik.WinControls.UI.RadListDataItem = New Telerik.WinControls.UI.RadListDataItem()
        Dim RadListDataItem4 As Telerik.WinControls.UI.RadListDataItem = New Telerik.WinControls.UI.RadListDataItem()
        Dim RadListDataItem5 As Telerik.WinControls.UI.RadListDataItem = New Telerik.WinControls.UI.RadListDataItem()
        Dim RadListDataItem6 As Telerik.WinControls.UI.RadListDataItem = New Telerik.WinControls.UI.RadListDataItem()
        Me.RadDropDownList1 = New Telerik.WinControls.UI.RadDropDownList()
        CType(Me.RadDropDownList1, System.ComponentModel.ISupportInitialize).BeginInit()
        Me.SuspendLayout()
        '
        'RadDropDownList1
        '
        Me.RadDropDownList1.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend
        Me.RadDropDownList1.DropDownAnimationEnabled = True
        RadListDataItem1.Text = "aper"
        RadListDataItem1.TextWrap = True
        RadListDataItem2.Text = "aaper"
        RadListDataItem2.TextWrap = True
        RadListDataItem3.Text = "ape"
        RadListDataItem3.TextWrap = True
        RadListDataItem4.Text = "per"
        RadListDataItem4.TextWrap = True
        RadListDataItem5.Text = "pants per"
        RadListDataItem5.TextWrap = True
        RadListDataItem6.Text = "aaa per"
        RadListDataItem6.TextWrap = True
        Me.RadDropDownList1.Items.Add(RadListDataItem1)
        Me.RadDropDownList1.Items.Add(RadListDataItem2)
        Me.RadDropDownList1.Items.Add(RadListDataItem3)
        Me.RadDropDownList1.Items.Add(RadListDataItem4)
        Me.RadDropDownList1.Items.Add(RadListDataItem5)
        Me.RadDropDownList1.Items.Add(RadListDataItem6)
        Me.RadDropDownList1.Location = New System.Drawing.Point(93, 126)
        Me.RadDropDownList1.Name = "RadDropDownList1"
        Me.RadDropDownList1.ShowImageInEditorArea = True
        Me.RadDropDownList1.Size = New System.Drawing.Size(106, 20)
        Me.RadDropDownList1.TabIndex = 1
        Me.RadDropDownList1.ThemeName = "ControlDefault"
        '
        'Form7
        '
        Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
        Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
        Me.ClientSize = New System.Drawing.Size(292, 273)
        Me.Controls.Add(Me.RadDropDownList1)
        Me.Name = "Form7"
        Me.Text = "Form7"
        CType(Me.RadDropDownList1, System.ComponentModel.ISupportInitialize).EndInit()
        Me.ResumeLayout(False)
        Me.PerformLayout()
  
    End Sub
    Friend WithEvents RadDropDownList1 As Telerik.WinControls.UI.RadDropDownList
  
  
    Public Class CustomAutoCompleteSuggestHelper
        Inherits AutoCompleteSuggestHelper
        Public Sub New(element As RadDropDownListElement)
            MyBase.New(element)
        End Sub
  
        Protected Overrides Function DefaultFilter(item As RadListDataItem) As Boolean
            Return item.Text.ToLower().Contains(Me.Filter.ToLower())
        End Function
  
        Public Overrides Sub AutoComplete(e As KeyPressEventArgs)
            MyBase.AutoComplete(e)
            If Me.DropDownList.Items.Count > 0 Then
                'Me.DropDownList.SelectedIndex = Me.DropDownList.FindString(Me.Filter)
            End If
        End Sub
  
        Private mFilter As String = String.Empty
        Protected Overrides ReadOnly Property Filter As String
            Get
                Return mFilter
            End Get
        End Property
  
        Public Overrides Sub ApplyFilterToDropDown(filter As String)
            Static filterFirstComparer As ListItemFilterAscendingComparer
            mFilter = filter
            If String.IsNullOrEmpty(filter) Then
                MyBase.ApplyFilterToDropDown(filter)
                Return
            End If
            With Me.DropDownList.ListElement
                .SelectionMode = SelectionMode.None
                .BeginUpdate()
                .Filter = Nothing
                .Filter = AddressOf DefaultFilter
                .SortStyle = Telerik.WinControls.Enumerations.SortStyle.Ascending
            End With
            ' will move all items that begin with the filter, to the top of the list
            If filterFirstComparer Is Nothing Then
                filterFirstComparer = New ListItemFilterAscendingComparer With {.filter = filter}
            Else
                filterFirstComparer.filter = filter
            End If
            Me.DropDownList.ListElement.ItemsSortComparer = filterFirstComparer
            Me.DropDownList.ListElement.EndUpdate()
        End Sub
  
        ''' <summary>
        ''' This class is used to compare data items when sorting in ascending order.
        ''' </summary>
        Private Class ListItemFilterAscendingComparer
            Implements System.Collections.Generic.IComparer(Of RadListDataItem)
  
            Public Property filter As String
  
            Public Overridable Function Compare(x As RadListDataItem, y As RadListDataItem) As Integer Implements System.Collections.Generic.IComparer(Of Telerik.WinControls.UI.RadListDataItem).Compare
                Dim ignoreCase = False
                If x.Owner IsNot Nothing Then
                    ignoreCase = Not x.Owner.CaseSensitiveSort
                End If
                Dim xStart = x.Text.StartsWith(filter, System.StringComparison.InvariantCultureIgnoreCase)
                Dim yStart = y.Text.StartsWith(filter, System.StringComparison.InvariantCultureIgnoreCase)
                If xStart AndAlso Not yStart Then
                    Return -1
                ElseIf yStart AndAlso Not xStart Then
                    Return 1
                End If
                Return String.Compare(x.Text, y.Text, ignoreCase)
            End Function
  
        End Class
    End Class
  
    Private Sub Form7_Load(sender As Object, e As System.EventArgs) Handles Me.Load
        RadDropDownList1.AutoCompleteMode = Windows.Forms.AutoCompleteMode.SuggestAppend
        RadDropDownList1.DropDownListElement.AutoCompleteSuggest = New CustomAutoCompleteSuggestHelper(RadDropDownList1.DropDownListElement)
    End Sub
End Class


5 Answers, 1 is accepted

Sort by
0
Accepted
Peter
Telerik team
answered on 21 Nov 2011, 01:00 PM
Hello Clive,

Thank you for writing.

This is a not very common scenario and I am afraid that you cannot distinct the items from items that start with a string and from items that contain the text.

You should implement a custom AutoCompleteSuggestHelper and override the DefaultFilter method.
I also recommend turning DropDownList's AutoCompleteMode property to Suggest mode only, please refer to the code snipped:

public class CustomAutoCompleteSuggestHelper : AutoCompleteSuggestHelper
{
    public CustomAutoCompleteSuggestHelper(RadDropDownListEditorElement element) : base(element)
    {        
    }
    
    protected override bool DefaultFilter(RadListDataItem item)
    {
        return item.Text.ToLower().StartsWith(this.Filter.ToLower()) || item.Text.ToLower().Contains(this.Filter.ToLower());
    }
    
    public override void AutoComplete(KeyPressEventArgs e)
    {
        base.AutoComplete(e);
        if (this.DropDownList.Items.Count > 0)
        {
            this.DropDownList.SelectedIndex = this.DropDownList.FindString(this.Filter);
        }
    }
}
//assign the new helper to DropDownList
radDropDownList.AutoCompleteSuggest = New CustomAutoCompleteSuggestHelper(radDropDownList.DropDownListElement);

I hope this helps.

Regards,
Peter
the Telerik team

Q2’11 SP1 of RadControls for WinForms is available for download (see what's new); also available is the Q3'11 Roadmap for Telerik Windows Forms controls.

0
Aaron
Top achievements
Rank 1
answered on 07 Jan 2012, 12:17 AM
Hello. I am trying to implement the above code sample in the newest version of the telerik RadDropDownList. It looks to me that I have all the correct using statements and included references but I cannot seem to locate the RadDropDownListEditorElement. I can use the RadDropDownListElement in the constructor of the CustomAutoCompleteSuggestHelper, but that does not seem to be exactly what you are indicating in the code.
0
Peter
Telerik team
answered on 11 Jan 2012, 05:09 PM
Hello Aaron,

The RadDropDownListEditorElement class is located in namespace Telerik.WinControls.UI in Telerik.WinControls.UI.dll assembly.

namespace Telerik.WinControls.UI
{
    /// <summary>
    /// Represents a DropDownList element used in RadDropDownListEditor
    /// </summary>
    [RadToolboxItemAttribute(false)]
    public class RadDropDownListEditorElement : ....

Make sure that you referenced this DLL in your application.

I hope that you find this information useful. Should you have any other questions, do not hesitate to contact us.

Greetings,
Peter
the Telerik team

SP1 of Q3’11 of RadControls for WinForms is available for download (see what's new).

0
Ken
Top achievements
Rank 1
answered on 23 May 2012, 10:40 PM
I just wanted to chime in here and say that I was having the same issues as Aaron, and that the RadDropDownListEditorElement  class is not within the Telerik.WinControls.UI.dll assembly as was stated. It actually resides in the Telerik.WinControls.GridView.dll assembly as pointed out here: http://www.telerik.com/help/winforms/t_telerik_wincontrols_ui_raddropdownlisteditorelement.html 

Furthermore, when attempting to use the solution provided by Peter, I can't get this to work. AutoCompleteSuggest is not a member of a RadDropDownList but it is a member of RadDropDownList.DropDownListElement. And passing a RadDropDownList.DropDownListElement as a RadDropDownListEditorElement does not work: 
"cannot convert from 'Telerik.WinControls.UI.RadDropDownListElement' to 'Telerik.WinControls.UI.RadDropDownListEditorElement' "



0
Peter
Telerik team
answered on 28 May 2012, 11:15 AM
Hello Ken,

Thank you for the clarification.

You are right - the type is located in GridView.dll. The AutoCompleteSuggest inheritor should accept RadDropDownListElement as a parameter.

public CustomAutoCompleteSuggestHelper(RadDropDownListElement owner) : base(owner){       
}

Please accept my apologies for the omission.

Do not hesitate to contact us if you have other questions.

Greetings,
Peter
the Telerik team
RadControls for WinForms Q1'12 release is now live! Check out what's new or download a free trial >>
Tags
DropDownList
Asked by
Clive
Top achievements
Rank 1
Answers by
Peter
Telerik team
Aaron
Top achievements
Rank 1
Ken
Top achievements
Rank 1
Share this question
or