I have code using an AutoCompleteStringCollection:
private void txtS_TextChanged(object sender, EventArgs e)
{
TextBox t = sender as TextBox;
string[] arr = this.dbService.GetAll();
if (t != null)
{
if (t.Text.Length >= 3)
{
AutoCompleteStringCollection collection = new AutoCompleteStringCollection();
collection.AddRange(arr);
this.txtSerial.AutoCompleteCustomSource = collection;
}
}
}
How can I get the event for "item selected" after user selects an AutoComplete suggestion? And value of field?
There's no such thing as chosen item Event for a textBox, which I believe you're using for the AutoComplete. What you could do is add a key down event to your textBox. There you could verify if the enter key was pressed (clicking on a suggested link is the same as pressing enter). Something like that:
private void textBox1_KeyDown(object sender, KeyEventArgs e) {
if (e.KeyData == Keys.Enter) {
String selItem = this.textBox1.Text;
}
}
Rather than focusing on detecting if an item from the autocomplete list was selected, instead you should check if the current value of the textbox is in the set of autocomplete entries.
if (txtSerial.AutoCompleteCustomSource.Contains(t.Text))
{
// Logic to handle an exact match being selected
...
}
else
{
// Update the autocomplete entries based on what was typed in
}
If the user typed in an exact string which happens to be be within the list of autocomplete values -- OR -- they select that value from the autocomplete list -- should this produce any different behavior? I think that in most cases it should not.
Short answer: make a custom event
Long answer:
You can intercept the KeyDown event of your textbox for numpad Enter or normal Enter and the mouse doubleclick event of the toolbox and compare the content of the toolbox then fire an event if they match that a delegate will pick up.
It depends a bit on the situation and workflow of your program but I have an example where I trigger the check on focuslost of the combobox. And then I check if the selected value is part of the collection:
private void cmbt1Name1_LostFocus(object sender, RoutedEventArgs e)
{
ComboBox cmb = sender as ComboBox;
FillFivePoints(cmb);
}
private void FillFivePoints(ComboBox usedCombobox)
{
if (txtSerial.AutoCompleteCustomSource.Contains(t.Text))
{
...
I have applied a ToolTip to textbox in C# such that the textbox has to accept the name of the user. In the ToolTip, I have types the instructions that only alphabets are welcome in the textbox, which is a success. But what I want is to make that ToolTip disappear when the user starts to type his name or moves to another textbox. The coding so far is;
ToolTip tt = new ToolTip();
String message = "Trying";
private void txtName_Enter(object sender, EventArgs e)
{
if (txtName.Text == String.Empty)
{
tt.Show(string.Empty, txtName, 0);
tt.Show(message, txtName, new Point(0, -2 * txtName.Height));
}
}
Help?
There is an event on the textbox called TextChanged. It fires as soon as the Text property of the control changes in value. Typing a character does change the Text property and therefor triggers the event.
Leveraging that knowledge, you can dismiss the tooltip as soon as Text is no longer empty like so:
private void txtName_TextChanged(object sender, EventArgs e)
{
var ctl = (Control) sender; // sender is a control
if (!String.IsNullOrEmpty(ctl.Text))
{
tt.SetToolTip(ctl, String.Empty);
}
}
Notice that this implementation can be used generically, by any control that you want to have this behavior.
This is my LostFocus event handler:
private void txtThrow_LostFocus(object sender, System.EventArgs e)
{
TextBox source = (TextBox)sender;
if (source.Text == "")
source.Text = "0";
}
This actually interferes with txtThrow_KeyPress, so that after I do my processing on my TextBox which accepts to only hold one character, I find it having two: mine and this zero you see here!! What I want to do is to keep txtThrow_KeyPress exactly as it is, but whenever the user types nothing, I want to enforce a zero.
What I can understand from here is that txtThrow_LostFocus is triggered before txtThrow_KeyPress is done with its job, since at the time txtThrow_LostFocus is triggered, the text is still empty. How can that be correct?!
I would recommend using the TextChanged event instead of the KeyPress event. I am assuming the text box could be empty already, and the user presses Backspace or something of the nature.
TextChanged event is triggered every time the text is changed within the field.
And the code you have should work perfectly fine when you fill the new event handler method with such. However, you may need to use
private void txtThrow_LostFocus_TextChanged(object sender, System.EventArgs e)
{
TextBox source = (TextBox)sender;
if (source.Text == "" || source.Text == null)
source.Text = "0"
}
Hope this helps!
Try to this code
private void txtThrow_LostFocus_TextChanged(object sender, System.EventArgs e)
{
TextBox source = (TextBox)sender;
if (string.nullorempty(source.text)
source.Text = "0"
}
Is there a way to find out if the "TextChanged" event is fired because
the user is typing into a textbox or
the programmer called myTextBox.Text = "something"?
Just to give you some color on this, I don't want to react when the user is typing each letter into the textbox so I am using the "Validated" event to catch when the user is done so I can react. The problem is I don't have a way to catch when the programmer does "myTextbox.Text = "something". The only way I know to catch changes there is to use TextChanged but then I don't want to be reacting when the user is typing each letter into the textbox. Any suggestions?
So in your "Formatted" Textbox class:
public override String Text{
get{return text;}
set
{
//perform validation/formatting
this.text = formattedValue;
}
this should allow you to format the text when it is changed by a programmer, the user input validation will still need to be handled in the validating event.
I will guess that you're creaing a UserControl that other developers will use, thus "end-user" programmers may set the text programmatically. I think the simplest thing would be to follow #jzworkman's suggestion and make a class that overrides the Text property setter. As #vulkanino notes, you should probably raise and catch the Validating event, though.
public class TextBoxPlus : TextBox {
public event CancelEventHandler ProgrammerChangedText;
protected void OnProgrammerChangedText(CancelEventArgs e) {
CancelEventHandler handler = ProgrammerChangedText;
if (handler != null) { handler(this, e); }
}
public override string Text {
get {
return base.Text;
}
set {
string oldtext = base.Text;
base.Text = value;
CancelEventArgs e = new CancelEventArgs();
OnProgrammerChangedText(e);
if (e.Cancel) base.Text = oldtext;
}
}
}
In your source, add the same handler to both the Validating and ProgrammerChangedText events:
// Somewhere...
textBoxPlus1.Validating += textBoxPlus1_Validating;
textBoxPlus1.ProgrammerChangedText += textBoxPlus1_Validating;
void textBoxPlus1_Validating(object sender, CancelEventArgs e) {
decimal d;
if (!Decimal.TryParse(textBoxPlus1.Text, out d)) {
e.Cancel = true;
}
}
If you want to perform validation, use the Validating event, not the Validated (which comes when it is too late to act).
That said, what's the real need here?
The Validating event is supplied an object of type CancelEventArgs. If
you determine that the control's data is not valid, you can cancel the
Validating event by setting this object's Cancel property to true. If
you do not set the Cancel property, Windows Forms will assume that
validation succeeded for that control, and raise the Validated event.
(http://msdn.microsoft.com/en-us/library/ms229603.aspx)
// This is the manual way, which is an alternative to the first way.
// Type 'this.TextChanged += ' into your form's constructor.
// Then press TAB twice, and you will have a new event handler.
this.TextChanged += new EventHandler(textBox1_TextChanged);
void textBox1_TextChanged(object sender, EventArgs e)
{
//put the logic here for your validation/requirements for validation
// ex. if (textbox1.Text=="something") {//don't validate}
//
}
I have a textbox that should disallow entering any special characters.
The user can enter :
A-Z
a-z
0-9
Space
How can I make the KeyDown event to do this?
Handling the KeyDown or KeyPress events is one way to do this, but programmers usually forget that a user can still copy-and-paste invalid text into the textbox.
A somewhat better way is to handle the TextChanged event, and strip out any offending characters there. This is a bit more complicated, as you have to keep track of the caret position and re-set it to the appropriate spot after changing the box's Text property.
Depending on your application's needs, I would just let the user type in whatever they want, and then flag the textbox (turn the text red or something) when the user tries to submit.
Just wanted to add some code for those ending up here by search:
private void Filter_TextChanged(object sender, EventArgs e)
{
var textboxSender = (TextBox)sender;
var cursorPosition = textboxSender.SelectionStart;
textboxSender.Text = Regex.Replace(textboxSender.Text, "[^0-9a-zA-Z ]", "");
textboxSender.SelectionStart = cursorPosition;
}
This is a change filter, so handles copy and paste, and preserves cursor position so that changing text in the middle works properly.
Note it uses the 'sender' to get the control name, allowing this one function to be linked to multiple textbox boxes, assuming they need the same filter. You can link multiple controls by going to the event section of a control and manually picking the function for the TextChanged event.
Use a regex to filter out the other characters. Or use Char.IsDigit, IsXXX methods to filter out unwanted characters. Lots of ways to do this.
Update: If you must use KeyDown then it seems that you need to also handle KeyPressed and set obEventArgs.Handled = true to disallow the characters. See the example on the KeyDown MSDN Page
Update: Now that you specify it's WPF. The below code will allow only a-z and A-Z characters to be entered into the textbox. Extend as needed...
private void _txtPath_KeyDown(object sender, KeyEventArgs e)
{
if ((e.Key < Key.A) || (e.Key > Key.Z))
e.Handled = true;
}
This will break if you copy-paste stuff into the text-box. Validate the entire text once the user leaves the control or when he clicks OK/Submit as MusicGenesis says.
private void _txtPath_KeyDown(object sender, KeyEventArgs e)
{
if ((e.Key < Key.A) || (e.Key > Key.Z))
e.Handled = true;
}
I think it's worth considering doing the filtering on the TextBox's TextChanged event. You can create an operation that gets rid of any non-valid characters from your text string. This is a bit more messy than blocking the KeyDown event.
But, I think this is the way to go because you are not blocking WPF's built-in KeyDown/Up event handling mechanisms, so copy/paste still works. You would be working at a higher level of abstractions so I think it will be easier to figure out what is going on.
I ran into this in silverlight and wrote something like this.
private string _filterRegexPattern = "[^a-zA-Z0-9]"; // This would be "[^a-z0-9 ]" for this question.
private int _stringMaxLength = 24;
private void _inputTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
if (!string.IsNullOrEmpty(_filterRegexPattern))
{
var text = _inputTextBox.Text;
var newText = Regex.Replace(_inputTextBox.Text, _filterRegexPattern, "");
if (newText.Length > _stringMaxLength)
{
newText = newText.Substring(0, _stringMaxLength);
}
if (text.Length != newText.Length)
{
var selectionStart = _inputTextBox.SelectionStart - (text.Length - newText.Length);
_inputTextBox.Text = newText;
_inputTextBox.SelectionStart = selectionStart;
}
}
}
I accomplish this with a custom Dependency Property. It's reusable for any TextBox control, is much faster and more efficient to use than building key events, and makes my code files much cleaner.
In addition, it can handle other input methods which does not trigger key events, such as pasting a value into the TextBox using the mouse.
The code for the custom DP looks like this:
// When set to a Regex, the TextBox will only accept characters that match the RegEx
/// <summary>
/// Lets you enter a RegexPattern of what characters are allowed as input in a TextBox
/// </summary>
public static readonly DependencyProperty AllowedCharactersRegexProperty =
DependencyProperty.RegisterAttached("AllowedCharactersRegex",
typeof(string), typeof(TextBoxProperties),
new UIPropertyMetadata(null, AllowedCharactersRegexChanged));
// Get
public static string GetAllowedCharactersRegex(DependencyObject obj)
{
return (string)obj.GetValue(AllowedCharactersRegexProperty);
}
// Set
public static void SetAllowedCharactersRegex(DependencyObject obj, string value)
{
obj.SetValue(AllowedCharactersRegexProperty, value);
}
// Events
public static void AllowedCharactersRegexChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
var tb = obj as TextBox;
if (tb != null)
{
if (e.NewValue != null)
{
tb.PreviewTextInput += Textbox_PreviewTextChanged;
DataObject.AddPastingHandler(tb, TextBox_OnPaste);
}
else
{
tb.PreviewTextInput -= Textbox_PreviewTextChanged;
DataObject.RemovePastingHandler(tb, TextBox_OnPaste);
}
}
}
public static void TextBox_OnPaste(object sender, DataObjectPastingEventArgs e)
{
var tb = sender as TextBox;
bool isText = e.SourceDataObject.GetDataPresent(DataFormats.Text, true);
if (!isText) return;
var newText = e.SourceDataObject.GetData(DataFormats.Text) as string;
string re = GetAllowedCharactersRegex(tb);
re = string.Format("[^{0}]", re);
if (Regex.IsMatch(newText.Trim(), re, RegexOptions.IgnoreCase))
{
e.CancelCommand();
}
}
public static void Textbox_PreviewTextChanged(object sender, TextCompositionEventArgs e)
{
var tb = sender as TextBox;
if (tb != null)
{
string re = GetAllowedCharactersRegex(tb);
re = string.Format("[^{0}]", re);
if (Regex.IsMatch(e.Text, re, RegexOptions.IgnoreCase))
{
e.Handled = true;
}
}
}
And it's used like this:
<TextBox Text="{Binding SomeValue, UpdateSourceTrigger=PropertyChanged}"
local:TextBoxHelpers.AllowedCharactersRegex="a-zA-Z0-9\s" />
I know that winForms have available a MaskedTextBox control, which lets you specify exactly this sort of thing. I don't know WPF, so I dunno if that's available there, but if it is, do that. Its MUCH easier than all this stuff with keypresses and events, and more robust too.
The easiest way to do this would be to included the Extended WPF Toolkit which has a control for doing exactly what you are asking for by specifying a mask.
http://wpftoolkit.codeplex.com/wikipage?title=MaskedTextBox&referringTitle=Home
It will also display the mask in the text box as you are inputting if required.
(It also has many other useful controls)
and your regExp could look like [0-9a-zA-Z]* to allow only English alphanumeric chracters
only alphanumeric TextBox WPF C#,
sorry for my english.. but with this code for WPF, c#, I only permit alphanumeric
private void txtTraslado_TextChanged(object sender, KeyEventArgs e)
{
if (((e.Key < Key.NumPad0)||(e.Key > Key.NumPad9))&&((e.Key < Key.A)||(e.Key > Key.Z)))
{
e.Handled = true;
}
}
Use Asp.NET AJAX Control Toolkit
<%# Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="asp" %>
And Use FilteredTextBoxExtender
<asp:TextBox ID="txt_gpf_no" runat="server" CssClass="textbox"
MaxLength="10"></asp:TextBox>
<asp:FilteredTextBoxExtender ID="FilteredTextBoxExtender_gpf_no" runat="server" Enabled="True"
TargetControlID="txt_gpf_no" FilterType="UppercaseLetters,LowercaseLetters,Custom" ValidChars="1234567890 ">
</asp:FilteredTextBoxExtender>
in my.Net Framework 4.5 C# application
private void txtRF_Register_Val_KeyDown(object sender, KeyEventArgs e)
{
//only enable alphanumeric
if (!(((e.KeyCode < Keys.NumPad0) || (e.KeyCode > Keys.NumPad9)) && ((e.KeyCode < Keys.A) || (e.KeyCode > Keys.E))))
{
e.SuppressKeyPress = false;
}
else
{
e.SuppressKeyPress = true;
}
}