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
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
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
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 >>
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!
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.
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
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
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.
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.
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
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.
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.
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,
We have a KB article handling a server-side auto-complete for the RadDropDownList: https://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
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!
The RadCheckedDropDownList supports auto-complete and multiple selections, so you can consider using it to implement the dynamic data loading:
- https://docs.telerik.com/devtools/winforms/dropdown-listcontrol-and-checkeddropdownlist/checkeddropdownlist/getting-started
- https://docs.telerik.com/devtools/winforms/dropdown-listcontrol-and-checkeddropdownlist/checkeddropdownlist/autocompletemodes
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
Hello Hristo,
I just built Dimitar's "633090csharp.zip" demo project at first step.
I try to find the solution with RadAutoCompleteBox.
Thank you
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
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!
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
Hello Dimitar,
Thank you, it works now! :)
Many thanks!