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

RadAutoCompleteBox with dynamic datasource

20 Answers 414 Views
AutoCompleteBox
This is a migrated thread and some comments may be shown as answers.
Giovanni
Top achievements
Rank 1
Iron
Giovanni asked on 23 Nov 2012, 02:33 PM
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,

20 Answers, 1 is accepted

Sort by
0
Svett
Telerik team
answered on 27 Nov 2012, 02:08 PM
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.
0
Robert Schoen
Top achievements
Rank 1
answered on 18 Jul 2013, 07:27 PM
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.
0
Dimitar
Telerik team
answered on 23 Jul 2013, 02:40 PM
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 >>
0
Edmund
Top achievements
Rank 1
answered on 05 Nov 2014, 08:24 PM
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!



0
George
Telerik team
answered on 07 Nov 2014, 11:43 AM
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.

 
0
Edmund
Top achievements
Rank 1
answered on 15 Nov 2014, 07:33 PM
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






0
Edmund
Top achievements
Rank 1
answered on 15 Nov 2014, 08:39 PM
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



0
Dimitar
Telerik team
answered on 19 Nov 2014, 03:15 PM
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.

 
0
Edmund
Top achievements
Rank 1
answered on 20 Nov 2014, 01:47 AM
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
0
Dimitar
Telerik team
answered on 21 Nov 2014, 04:38 PM
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.

 
0
Edmund
Top achievements
Rank 1
answered on 24 Nov 2014, 07:47 PM
Thank you very much.  This is working great!
0
Sandor
Top achievements
Rank 1
answered on 14 Nov 2018, 03:12 PM

Hey Guys,

we need exactly this scenario, but in current version we cannot reproduce this functionality, or at least not the desired one. After I press a key [T], I get the result set, however pressing the second key [e] puts the label of the first result element and then my next, so my label looks like "Test 0e".

Could you please advise on how to solve this?

Thank you,

0
Hristo
Telerik team
answered on 15 Nov 2018, 09:24 AM
Hello Sandor,

We have a KB article handling a server-side auto-complete for the RadDropDownListhttps://www.telerik.com/support/kb/winforms/details/server-side-auto-complete-for-raddropdownlist. The solution in the article will only load in the memory items matching the input. I hope that a similar approach would fit your local setup.

Regards,
Hristo
Progress Telerik
Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
0
Sandor
Top achievements
Rank 1
answered on 15 Nov 2018, 04:19 PM

Hello Hristo,

We need the multi select functionality, so the RadDropDownList will not work for us. Is there a way to make this happen with the AutoCompleteBox?

Thank you!

 

0
Hristo
Telerik team
answered on 16 Nov 2018, 09:54 AM
Hi Sandor,

The RadCheckedDropDownList supports auto-complete and multiple selections, so you can consider using it to implement the dynamic data loading:
About the RadAutoCompleteBox, the approaches suggested previously are working well on my end and I am not sure about the nature of your issue. If you would like us to investigate your project, you can open a support ticket and send it over to us.

Regards,
Hristo
Progress Telerik
Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
0
Sandor
Top achievements
Rank 1
answered on 19 Nov 2018, 12:46 PM

Hello Hristo,

I just built Dimitar's "633090csharp.zip" demo project at first step.

I try to find the solution with RadAutoCompleteBox.

Thank you

0
Dimitar
Telerik team
answered on 20 Nov 2018, 08:34 AM
Hello Sandor,

I have tested this and the final solution is this:
void RadAutoCompleteBox1KeyPress(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 = (from x in list where x.Contains(value) select x).Take(10);
 
    if (result != null)
    {
        radAutoCompleteBox1.AutoCompleteDataSource = result;
    }
}

Let me know how it works for you.

Regards,
Dimitar
Progress Telerik
Get quickly onboard and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
0
Sandor
Top achievements
Rank 1
answered on 20 Nov 2018, 02:38 PM

Hello Dimitar,

Still I get the same result, I've made a couple of screenshots for explanation. The problem is obviously on step 4. We are using the latest Telerik library with Win 10 and Win 7 , and we get the same result in both.

We assume that the problem is that the change of the  AutoCompleteDataSource property fires an inner textchange event.

Any suggestions?

Thank You!

0
Dimitar
Telerik team
answered on 21 Nov 2018, 09:05 AM
Hello Sandor,

Yes, setting the data source will trigger item selection which will change the text. To avoid this you can use the following approach:
void RadAutoCompleteBox1KeyPress(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 = (from x in list where x.Contains(value) select x).Take(10);
 
    if (result != null)
    {
        radAutoCompleteBox1.AutoCompleteMode = AutoCompleteMode.None;
        radAutoCompleteBox1.AutoCompleteDataSource = result;            
        radAutoCompleteBox1.AutoCompleteMode = AutoCompleteMode.Suggest;
    }
}

Should you have any other questions do not hesitate to ask.

Regards,
Dimitar
Progress Telerik
Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
0
Sandor
Top achievements
Rank 1
answered on 21 Nov 2018, 09:19 AM

Hello Dimitar,

Thank you, it works now! :)

Many thanks!

 

Tags
AutoCompleteBox
Asked by
Giovanni
Top achievements
Rank 1
Iron
Answers by
Svett
Telerik team
Robert Schoen
Top achievements
Rank 1
Dimitar
Telerik team
Edmund
Top achievements
Rank 1
George
Telerik team
Sandor
Top achievements
Rank 1
Hristo
Telerik team
Share this question
or