As the title says really. I've had a look at inheriting from TextBox, but the only sensible override was "OnKeyDown", but that just gives me a key from the Key enum (with no way to use Char.IsNumeric()).
Take a look at NumericUpDown in the Toolkit http://codeplex.com/Silverlight and maybe you can use that or look at the source to implement your own numeric textbox.
I took Nidhal's suggested answer and edited it a bit to handle the shift case for the characters above the digits (ie. !@#$%^&*()) since that solution will still allow those characters in the textbox.
private void NumClient_KeyDown(object sender, KeyEventArgs e)
{
// Handle Shift case
if (Keyboard.Modifiers == ModifierKeys.Shift)
{
e.Handled = true;
}
// Handle all other cases
if (!e.Handled && (e.Key < Key.D0 || e.Key > Key.D9))
{
if (e.Key < Key.NumPad0 || e.Key > Key.NumPad9)
{
if (e.Key != Key.Back)
{
e.Handled = true;
}
}
}
}
Visit http://www.dataartist.net/blog/post/Silverlight-Behavior-Modifications-13-NumericOnlyBehavior.aspx or use TextBox behavior as below
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interactivity;
namespace DataArtist
{
public class NumericOnly : Behavior<TextBox>
{
private string Text { get; set; }
private bool shiftKey;
public bool StripOnExit { get; set; }
public NumericOnly()
{
StripOnExit = false;
}
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.KeyDown += KeyDown;
AssociatedObject.KeyUp += KeyUp;
AssociatedObject.GotFocus += GotFocus;
AssociatedObject.LostFocus += LostFocus;
}
void KeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.Shift)
{
shiftKey = false;
}
}
void KeyDown(object sender, KeyEventArgs e)
{
if (StripOnExit != false || e.Key == Key.Tab || e.Key == Key.Enter)
{
return;
}
if (e.Key == Key.Shift)
{
shiftKey = true;
}
else
{
if (IsNumericKey(e.Key) == false)
{
e.Handled = true;
}
}
}
void GotFocus(object sender, RoutedEventArgs e)
{
Text = AssociatedObject.Text;
}
private void LostFocus(object sender, RoutedEventArgs e)
{
if (AssociatedObject.Text == Text)
{
return;
}
string content = string.Empty;
foreach (var c in AssociatedObject.Text)
{
if (Char.IsNumber(c) == true)
{
content += c;
}
}
AssociatedObject.Text = content;
}
public bool IsNumericKey(Key key)
{
if (shiftKey == true)
{
return false;
}
string code = key.ToString().Replace("NumPad", "D");
if (code[0] == 'D' && code.Length > 1)
{
return (Char.IsNumber(code[1]));
}
return false;
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.KeyDown -= KeyDown;
AssociatedObject.LostFocus -= LostFocus;
AssociatedObject.GotFocus -= GotFocus;
}
}
}
private void Numclient_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key < Key.D0 || e.Key > Key.D9)
{
if (e.Key < Key.NumPad0 || e.Key > Key.NumPad9)
{
if (e.Key != Key.Back && e.Key != Key.Shift)
{
e.Handled = true;
}
}
}
}
Take a look at NumericUpDown in the Toolkit http://codeplex.com/Silverlight and maybe you can use that or look at the source to implement your own numeric textbox.
Take a look at this one, it uses an attached property over the textbox. I am using it and it does work. http://weblogs.asp.net/manishdalal/archive/2008/09/24/prevention-the-first-line-of-defense-with-attach-property-pixie-dust.aspx
private void TextBox_KeyDown(object sender, KeyEventArgs e)
{
bool isDigit = e.Key >= Key.D0 && e.Key < Key.D9 || e.Key == Key.NumPad0 || e.Key == Key.NumPad1 || e.Key == Key.NumPad2 || e.Key == Key.NumPad3 || e.Key == Key.NumPad4 || e.Key == Key.NumPad5 || e.Key == Key.NumPad6 ||
e.Key == Key.NumPad7 || e.Key == Key.NumPad8 || e.Key == Key.NumPad9 ||e.Key == Key.Back || e.Key == Key.Delete || e.Key == Key.Left || e.Key == Key.Right;
if (isDigit) { }
else
e.Handled = true;
}
It works:
static bool AltGrIsPressed;
void Numclient_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.Alt)
{
AltGrIsPressed = false;
}
}
void Numclient_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Alt)
{
AltGrIsPressed = true;
}
if (Keyboard.Modifiers == ModifierKeys.Shift || AltGrIsPressed == true)
{
e.Handled = true;
}
if (e.Handled == false && (e.Key < Key.D0 || e.Key > Key.D9))
{
if (e.Key < Key.NumPad0 || e.Key > Key.NumPad9)
{
if (e.Key != Key.Back)
{
e.Handled = true;
}
}
}
}
private void txtbox_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.D0 || e.Key == Key.D1 || e.Key == Key.D2 || e.Key == Key.D3 || e.Key == Key.D4 || e.Key == Key.D5 || e.Key == Key.D6 || e.Key == Key.D7 || e.Key == Key.D8 || e.Key == Key.D9 || e.Key == Key.NumPad0 || e.Key == Key.NumPad1 || e.Key == Key.NumPad2 || e.Key == Key.NumPad3 || e.Key == Key.NumPad4 || e.Key == Key.NumPad5 || e.Key == Key.NumPad6 || e.Key == Key.NumPad7 || e.Key == Key.NumPad8 || e.Key == Key.NumPad9)
e.Handled = false;
else
e.Handled = true;
}
I know it has been answered, but I found no proper solution that handles all special cases, most answers here swallows some important keys like Home, End, Tab, Shift+ any thing, ..etc.
So, I developed my own implementation as it may help somebody!
public class IntegerTextBox : TextBox
{
/// <summary>
/// To be raised whenever integer value changed
/// </summary>
public event EventHandler ValueChanged;
/// <summary>
/// To restore if the user entered invalid characters
/// </summary>
private int lastSavedValue = 0;
private int lastSelectionStart = 0;
private int lastSelectionLength = 0;
public int IntegerValue
{
get
{
//the default value is 0 if there is no text in the textbox
int value = 0;
int.TryParse(Text, out value);
return value;
}
set
{
if (this.Text.Trim() != value.ToString())
{
Text = value.ToString();
}
}
}
public IntegerTextBox()
: base()
{
this.LostFocus += (sender, e) =>
{
//if the user clears the text the text box and leaves it, set it to default value
if (string.IsNullOrWhiteSpace(this.Text))
IntegerValue = 0;
};
this.Loaded += (sender, e) =>
{
//populate the textbox with Initial IntegerValue (default = 0)
this.Text = this.IntegerValue.ToString();
};
this.TextChanged += (sender, e) =>
{
int newValue = 0;
if (int.TryParse(this.Text, out newValue)) //this will handle most cases like number exceeds the int max limits, negative numbers, ...etc.
{
if (string.IsNullOrWhiteSpace(Text) || lastSavedValue != newValue)
{
lastSavedValue = newValue;
//raise the event
EventHandler handler = ValueChanged;
if (handler != null)
handler(this, EventArgs.Empty);
}
}
else
{
//restore previous number
this.Text = lastSavedValue.ToString();
//restore selected text
this.SelectionStart = lastSelectionStart;
this.SelectionLength = lastSelectionLength;
}
};
this.KeyDown += (sender, e) =>
{
//before every key press, save selection start and length to handle overwriting selected numbers
lastSelectionStart = this.SelectionStart;
lastSelectionLength = this.SelectionLength;
};
}
}
The above code has a single disadvantage, TextChanged event will be raised frequently, but since we need an integer
textbox, then we can rely on ValueChanged
instead!
Extend the normal Silverlight Textbox control. Add this code inside the extended TextBox class:
string nums = "1234567890";
string lastText = "";
int lastSelStart = 0;
protected override void TextChanged(object sender, TextChangedEventArgs e)
{
if(!nums.Contains(this.Text.Substring(this.Text.Length -1)))
{
this.Text = lastText;
this.SelectionStart = lastSelStart;
return;
}
lastText = this.Text;
lastSelStart = this.SelectionStart;
}
Why is everyone not doing the hard work of just handling them all?
Here (this is perfection):
<TextBox KeyDown="TextBox_KeyDown" />
private void TextBox_KeyDown(object sender, KeyEventArgs e)
{
var _Letter = string.Empty;
switch (e.Key)
{
case Key.A: _Letter = "A"; break;
case Key.Add: _Letter = "+"; break;
case Key.Alt: break;
case Key.B: _Letter = "B"; break;
case Key.Back: break;
case Key.C: _Letter = "C"; break;
case Key.CapsLock: break;
case Key.Ctrl: break;
case Key.D: _Letter = "D"; break;
case Key.D0: _Letter = "0"; break;
case Key.D1: _Letter = "1"; break;
case Key.D2: _Letter = "2"; break;
case Key.D3: _Letter = "3"; break;
case Key.D4: _Letter = "4"; break;
case Key.D5: _Letter = "5"; break;
case Key.D6: _Letter = "6"; break;
case Key.D7: _Letter = "7"; break;
case Key.D8: _Letter = "8"; break;
case Key.D9: _Letter = "9"; break;
case Key.Decimal: _Letter = "."; break;
case Key.Delete: break;
case Key.Divide: _Letter = "/"; break;
case Key.Down: break;
case Key.E: _Letter = "E"; break;
case Key.End: break;
case Key.Enter: break;
case Key.Escape: break;
case Key.F: _Letter = "F"; break;
case Key.F1: break;
case Key.F10: break;
case Key.F11: break;
case Key.F12: break;
case Key.F2: break;
case Key.F3: break;
case Key.F4: break;
case Key.F5: break;
case Key.F6: break;
case Key.F7: break;
case Key.F8: break;
case Key.F9: break;
case Key.G: _Letter = "G"; break;
case Key.H: _Letter = "H"; break;
case Key.Home: break;
case Key.I: _Letter = "I"; break;
case Key.Insert: break;
case Key.J: _Letter = "J"; break;
case Key.K: _Letter = "K"; break;
case Key.L: _Letter = "L"; break;
case Key.Left: break;
case Key.M: _Letter = "M"; break;
case Key.Multiply: _Letter = "*"; break;
case Key.N: _Letter = "N"; break;
case Key.None: break;
case Key.NumPad0: _Letter = "0"; break;
case Key.NumPad1: _Letter = "1"; break;
case Key.NumPad2: _Letter = "2"; break;
case Key.NumPad3: _Letter = "3"; break;
case Key.NumPad4: _Letter = "4"; break;
case Key.NumPad5: _Letter = "5"; break;
case Key.NumPad6: _Letter = "6"; break;
case Key.NumPad7: _Letter = "7"; break;
case Key.NumPad8: _Letter = "8"; break;
case Key.NumPad9: _Letter = "9"; break;
case Key.O: _Letter = "O"; break;
case Key.P: _Letter = "P"; break;
case Key.PageDown: break;
case Key.PageUp: break;
case Key.Q: _Letter = "Q"; break;
case Key.R: _Letter = "R"; break;
case Key.Right: break;
case Key.S: _Letter = "S"; break;
case Key.Shift: break;
case Key.Space: _Letter = " "; break;
case Key.Subtract: _Letter = "-"; break;
case Key.T: _Letter = "T"; break;
case Key.Tab: break;
case Key.U: _Letter = "U"; break;
case Key.Unknown: break;
case Key.Up: break;
case Key.V: _Letter = "V"; break;
case Key.W: _Letter = "W"; break;
case Key.X: _Letter = "X"; break;
case Key.Y: _Letter = "Y"; break;
case Key.Z: _Letter = "Z"; break;
default: break;
}
var _Text = (sender as TextBox).Text + _Letter;
double _Double;
e.Handled = !double.TryParse(_Text, out _Double);
}
}
© 2022 - 2024 — McMap. All rights reserved.