RadAutoCompleteBox with dynamic datasource

12 posts, 0 answers
  1. Giovanni
    Giovanni avatar
    37 posts
    Member since:
    Feb 2011

    Posted 23 Nov 2012 Link to this post

    Hi,
    I'm trying to use the RadAutoCompleteBox with a big amount of data.
    Because of this, I would like to load data dynamically, based on the current input string.
    For example, if the user is typing "ab" I want to start a thread to load from a database all the record filtered by "ab" string (and limited to a max number of record).

    Is this automacally supported by the control?
    Have someone developed a solution like this?

    Thank you,
  2. Svett
    Admin
    Svett avatar
    728 posts

    Posted 27 Nov 2012 Link to this post

    Hi Giovanni,

    The controls in Winforms are not thread safe. The operations that relate on Windows forms controls should be executed in the UI thread that owns the control. Such approach will cause throwing exceptions inside the RadAutoCompleteBox.

    Kind regards,
    Svett
    the Telerik team
    Q3’12 of RadControls for WinForms is available for download (see what's new). Get it today.
  3. UI for WinForms is Visual Studio 2017 Ready
  4. Robert Schoen
    Robert Schoen avatar
    17 posts
    Member since:
    Sep 2008

    Posted 18 Jul 2013 Link to this post

    I also want to provide a dynamic list to choose from.   However, I don't need to have any extra thread.   I am willing to use the current thread.   I have searched many examples but they all tend to give a single complete table rather than pre-filtering the results on what the user has already entered.   I will be working with a large number of entries so it is important that I isolate the results to the top 20 most relevant results.
  5. Dimitar
    Admin
    Dimitar avatar
    1414 posts

    Posted 23 Jul 2013 Link to this post

    Hello Giovanni,

    Thank you for writing.

    You can preload or filter your data source on every user keystroke and then assign it to the RadAutoCompleteBox. I have prepared and attached a demo project where I have BindingList with some text elements in it. On every keystroke I take the first 10 elements that are containing the value in autocompletebox. Then I am assigning the result as autocompletebox data source. Now the autocompletebox will let me choose from the first 10 elements in the list. 

    I hope this approach will fit in your case. Should you have further questions, I would be glad to help.

    Regards, Dimitar
    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 >>
  6. Edmund
    Edmund avatar
    9 posts
    Member since:
    Oct 2014

    Posted 05 Nov 2014 in reply to Dimitar Link to this post

    I have the same issue where I need to be able to dynamically change the datasource backing the autocomplete control because the data lives in a database.  The solution posted doesn't really work in that it assumes the user is only trying to type in a single token to the autocomplete box which I can't imagine is a common use case for the control.  It also doesn't handle the user deleting text out of the autocomplete box.

    Is there a better work around for this?  I tried something like this:

    private void tagAutoCompleteBox_TextChanged(object sender, EventArgs e)
    {           
        var tokens = tagAutoCompleteBox.Text.Split(tagAutoCompleteBox.Delimiter);
        string token = tokens[tokens.Length - 1];
        // Look up Token in database then populate BindingList           
    }

    But this only works if the user is adding tokens to the end of the autocomplete box.  The dynamic datasource or database backed datasource seems like it would be a common use case for autocomplete.  It would be nice if there was an elegant solution for this problem.

    Thanks!



  7. George
    Admin
    George avatar
    500 posts

    Posted 07 Nov 2014 Link to this post

    Hi Edmund,

    Thank you for writing.

    You can get the TextBlock under the caret and use its text for autocomplete. Here is a modified version of the code:
    void radAutoCompleteBox1_TextChanged(object sender, EventArgs e)
    {
        int caretIndex = this.radAutoCompleteBox1.TextBoxElement.CaretIndex;
        var nonTokenizedBlock = this.radAutoCompleteBox1.TextBoxElement.ViewElement.Children
            .OfType<TextBlockElement>()
            .LastOrDefault(x => caretIndex >= x.Offset && caretIndex <= x.Offset + x.Length);
     
        if (nonTokenizedBlock == null)
        {
            return;
        }
     
        string value = nonTokenizedBlock.Text;
     
        var result = this.data.Where(x => x.Contains(value)).Take(10).ToList();
     
        this.autoCompleteDataSource.Clear();
        if (result.Any())
        {
            result.ForEach(x => autoCompleteDataSource.Add(x));
        }
    }

    I hope this will help.

    Regards,
    George
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  8. Edmund
    Edmund avatar
    9 posts
    Member since:
    Oct 2014

    Posted 15 Nov 2014 in reply to George Link to this post

    Hi George,

    Thank you for assistance.  I could be using this wrong but it seems like there might be a problem when hitting the "backspace" key and using your provided solution.

    Based on my investigation it seems like when you hit the backspace key, the CaretIndex position obtained in the TextChanged event is the position of the caret prior to the backspace event occurring.  However, the value of TextBlockElement is already updated to reflect the affect of the backspace.

    So for example if you have the word "test" in your autocomplete textbox like this (so "test" is our token of length 4 with offset 0)

    test
    (caret index= 4) (token.Offset = 0, token.Length=4)
    <press backspace>
    tes
    TextChangedEvent Values: (caret index = 4) (token.Offset = 0, token.Length = 3)

    So what happens is that in the TextChangedEvent the caret index is 4 (which is the position before the backspace takes affect), but the token.Length is 3 (which is after the backspace takes affect).  The end result is that the test of caretIndex <= x.Offset + x.Length does not pass and the token is not processed for autocompleting.

    I'm not sure if this is a bug or expected behavior (or if I'm doing something wrong).  Thank you!

    Best Regards,

    Ed






  9. Edmund
    Edmund avatar
    9 posts
    Member since:
    Oct 2014

    Posted 15 Nov 2014 in reply to Edmund Link to this post

    I just stumbled into another even larger problem than the one I previously wrote about regarding BackSpace.  The issue is that once the autocomplete dropdown list appears, if the user uses the keyboard up and down arrows to navigate the autocomplete options, the TextChanged event is fired and the text that is used is the item that was highlighted in the drop down list.

    This of course causes the dropdownlist to update but it will now only show the item that was selected when the user started using the up and down arrow keys.

    How can we make the AutoCompleteTextBox behave like the DropDownList autocomplete when using a server side datasource?  Is there a way to use a custom AutoCompleteSuggestHelper with AutoCompleteTextBox as I have a working version of that?  Using the TextChanged event seems like it will not work (at least as suggested) since it fires when the user is scrolling through the autocomplete drop down list options.

    I attached a screenshot to illustrate the problem.

    Best Regards,

    Ed



  10. Dimitar
    Admin
    Dimitar avatar
    1414 posts

    Posted 19 Nov 2014 Link to this post

    Hello Edmund,

    Thank you for writing back.

    Perhaps it would be better to use the KeyPress event. It is better since this event would not fire when the item is changed with the arrow keys:
    void radAutoCompleteBox1_KeyPress(object sender, KeyPressEventArgs e)
    {         
        int caretIndex = this.radAutoCompleteBox1.TextBoxElement.CaretIndex;
        var nonTokenizedBlock = this.radAutoCompleteBox1.TextBoxElement.ViewElement.Children
            .OfType<TextBlockElement>()
            .LastOrDefault(x => caretIndex >= x.Offset && caretIndex <= x.Offset + x.Length);
     
        if (nonTokenizedBlock == null)
        {
            return;
        }
     
        string value = nonTokenizedBlock.Text+e.KeyChar.ToString();
        var result = this.data.Where(x => x.Contains(value)).Take(10).ToList();
     
        this.autoCompleteDataSource.Clear();
        if (result.Any())
        {
            result.ForEach(x => autoCompleteDataSource.Add(x));
        }
    }

    Let me know if you have additional questions.
     
    Regards,
    Dimitar
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  11. Edmund
    Edmund avatar
    9 posts
    Member since:
    Oct 2014

    Posted 19 Nov 2014 in reply to Dimitar Link to this post

    Hello Dimitar,

    Thank you for the response.  The KeyPress event does work better in that the arrow key presses do not cause issues.  However, the problem now is that the value of the nonTokenizedBlock is one character behind.

    In other words lets say the AutoCompleteBox has the text "Hell Worl" in it.  The user then presses the "d" key.  This causes the "KeyPress" event to fire.  Unfortunately at this point in time, the nonTokenizedBlock value is "Hello Worl" and not "Hello World".  In other words, the KeyPress event seems to fire before the value of the "this.radAutoCompleteBox1.TextBoxElement.ViewElement.Children" is updated to reflect the new character.

    This means that the autocomplete suggestions are always one character behind.  

    Is there a way around this behavior?

    Best Regards,

    Ed
  12. Dimitar
    Admin
    Dimitar avatar
    1414 posts

    Posted 21 Nov 2014 Link to this post

    Hello Edmund,

    Thank you for writing back.

    I have noticed that and I have added the char in my code:
    string value = nonTokenizedBlock.Text+e.KeyChar.ToString();

    Let me know if you have additional questions.
     
    Regards,
    Dimitar
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  13. Edmund
    Edmund avatar
    9 posts
    Member since:
    Oct 2014

    Posted 24 Nov 2014 in reply to Dimitar Link to this post

    Thank you very much.  This is working great!
Back to Top
UI for WinForms is Visual Studio 2017 Ready