Autocomplete combobox

  • Thread starter Thread starter Simon Harvey
  • Start date Start date
S

Simon Harvey

Hi Guys,

I have a small problem with the Windows Forms Combobox control.

I need to allow it to have its Autocomplete behaviour enabled so that
the user can type in items and have the combo suggest values. This works
fine apart from the fact that it allows the user to add entirely new
items to the list - which causes validation problems later on.

Essentially what I would like is for the combobox to work exactly as it
does now, with the exception that if the user presses a key that would
mean that the new text would no longer represent a valid item in the
list - the control should just totally ignore the key press. It should
be as though the user hadn't pressed the key at all.

I've created a class that inherits from the Windows Forms combobox class
and that all works fine - I just can't figure out what to do from there.
I've tried handling things like the TextChanged event and KeyDown event
but I haven't been able to figure out how to get the correct effect.

Does anyone have an example of how to do this? I'm sure it must be very
simple, but I've never really inherited from an existing control.

Any help would be much appreciated

Many thanks in advance

S
 
Hi Mel,

Thats doesn't actually solve the issue because it prevents the user from
typing into the combobox.

Don't ask me why, but the client wants to be able to type into the list
but be restricted to only those items in the list

Many thanks

Simon
 
Hi Cor,

Thanks very much for your answer.

Hmm - I'm not quite sure how it would work. I've been trying to do
something whereby I handle the key press event and detect if the user is
about to enter a character that would be invalid.

I can stop the user from entering the bogus character, but unfortunately
something I'm doing seems to prevent the remainder of the text of the
target item from remaining selected. I'm doing it in the KeyPress event
and whatever I'm doing to prevent the users keypress from continuing
seems to be interfering with the normal autocomplete behaviour of the
control because when I kill the users action, the control immediately
deselects the users text - which in effect kills the autocomplete behaviour.

Sorry I hope that makes sense. I've copied the code of my control below
just in case it helps. I'm really close to getting it to work - I just
need to figure out how to stop my code from interfering with the
autocomplete part that the control does itself.... :-(


Thanks again for your thoughts

S

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace AutoCompleteCombo {

public class CustomCombobox: ComboBox {

public CustomCombobox()
: base() {
}

protected override void OnKeyPress(KeyPressEventArgs e) {
string startOfText = null;
string proposedComboValue = null;

Console.Out.WriteLine(e.KeyChar.ToString());

// If the character entered by the user is not a valid
number/letter/symbol etc, we don't want to bother with our masking
// logic as the user is probably just pressing the
delete/backspace key or something similar
if (Char.IsLetterOrDigit(e.KeyChar) == false &&
Char.IsPunctuation(e.KeyChar) == false && Char.IsSymbol(e.KeyChar) ==
false) {
base.OnKeyPress(e);

return;

}

# region [-- Determine Proposed Value --]

startOfText = this.Text.Substring(0, this.SelectionStart);

Console.Out.WriteLine("Start Value: " + startOfText);

// If the character that the user has just provided would
create a string that doesn't exist in our list of items, we need
// to prevent the key press from continuing

proposedComboValue = startOfText +
e.KeyChar.ToString().ToLower();
Console.Out.WriteLine("Proposed Value: " + proposedComboValue);

# endregion

# region [-- Determine if Proposed Value Is Valid --]

foreach (object currentListItem in this.Items) {

// If we find at least one item in the list that starts
with the proposed text, we know that the user should be allowed
// to continue with what they've done
if
(currentListItem.ToString().ToLower().StartsWith(proposedComboValue) ==
true) {
base.OnKeyPress(e);

Console.Out.WriteLine("Value is in the list");

return;

}

}

# endregion


// If we reach here it means that the user has attempted to
add a character that would mean that the text entered in the combo
// no longer represents a valid list item.
Console.Out.WriteLine("Value is NOT in the list");

// Prevent the KeyPressEvent from continuing by marking the
event as "handled"
e.Handled = true;

}

private string FindFirstMatchingItem(string targetText) {
string result = null;

foreach (object currentItem in this.Items) {

if
(currentItem.ToString().ToLower().StartsWith(targetText) == true) {
return currentItem.ToString();
}

}

return result;
}

}

}
 
Simon,

http://groups.google.com/group/microsoft.public.dotnet.languages.csharp/msg/cb2df568c7b5c0c6

I hope this helps, I did it never this way but it should go

Cor

Simon Harvey said:
Hi Cor,

Thanks very much for your answer.

Hmm - I'm not quite sure how it would work. I've been trying to do
something whereby I handle the key press event and detect if the user is
about to enter a character that would be invalid.

I can stop the user from entering the bogus character, but unfortunately
something I'm doing seems to prevent the remainder of the text of the
target item from remaining selected. I'm doing it in the KeyPress event
and whatever I'm doing to prevent the users keypress from continuing seems
to be interfering with the normal autocomplete behaviour of the control
because when I kill the users action, the control immediately deselects
the users text - which in effect kills the autocomplete behaviour.

Sorry I hope that makes sense. I've copied the code of my control below
just in case it helps. I'm really close to getting it to work - I just
need to figure out how to stop my code from interfering with the
autocomplete part that the control does itself.... :-(


Thanks again for your thoughts

S

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace AutoCompleteCombo {

public class CustomCombobox: ComboBox {

public CustomCombobox()
: base() {
}

protected override void OnKeyPress(KeyPressEventArgs e) {
string startOfText = null;
string proposedComboValue = null;

Console.Out.WriteLine(e.KeyChar.ToString());

// If the character entered by the user is not a valid
number/letter/symbol etc, we don't want to bother with our masking
// logic as the user is probably just pressing the
delete/backspace key or something similar
if (Char.IsLetterOrDigit(e.KeyChar) == false &&
Char.IsPunctuation(e.KeyChar) == false && Char.IsSymbol(e.KeyChar) ==
false) {
base.OnKeyPress(e);

return;

}

# region [-- Determine Proposed Value --]

startOfText = this.Text.Substring(0, this.SelectionStart);

Console.Out.WriteLine("Start Value: " + startOfText);

// If the character that the user has just provided would
create a string that doesn't exist in our list of items, we need
// to prevent the key press from continuing

proposedComboValue = startOfText +
e.KeyChar.ToString().ToLower();
Console.Out.WriteLine("Proposed Value: " +
proposedComboValue);

# endregion

# region [-- Determine if Proposed Value Is Valid --]

foreach (object currentListItem in this.Items) {

// If we find at least one item in the list that starts
with the proposed text, we know that the user should be allowed
// to continue with what they've done
if
(currentListItem.ToString().ToLower().StartsWith(proposedComboValue) ==
true) {
base.OnKeyPress(e);

Console.Out.WriteLine("Value is in the list");

return;

}

}

# endregion


// If we reach here it means that the user has attempted to
add a character that would mean that the text entered in the combo
// no longer represents a valid list item.
Console.Out.WriteLine("Value is NOT in the list");

// Prevent the KeyPressEvent from continuing by marking the
event as "handled"
e.Handled = true;

}

private string FindFirstMatchingItem(string targetText) {
string result = null;

foreach (object currentItem in this.Items) {

if
(currentItem.ToString().ToLower().StartsWith(targetText) == true) {
return currentItem.ToString();
}

}

return result;
}

}

}

Hi Simon,

Why not simply check it using the method findstring in the textchanged
event

http://msdn.microsoft.com/en-us/library/system.windows.forms.combobox.findstring(VS.71).aspx
Cor
 
Hi Cor

Thanks for that. I am using the handled event but unfortunately it seems
to interfere with the autocomplete functionailty in that it deselects
all the text in the control when the user enters an invalid character.

I just need to figure out why doing e.handled = true deselects the text
in the control cos I really wish it didn't!

Thanks agaain though

S
 
Back
Top