is use a behavior(Blend SDK System.Windows.Interactivity) instead of handling PreviewTextInput directly. i do this because of reusability and also you should know that the space is not handled with TextInput and also Pasting is not handled. btw i think Jonathan and Felice Pollano are right, regarding to your "decimal point" problem.
public class TextBoxInputBehavior : Behavior<TextBox> { public TextBoxInputMode InputMode { get; set; } public TextBoxInputBehavior() { this.InputMode = TextBoxInputMode.None; } protected override void OnAttached() { base.OnAttached(); AssociatedObject.PreviewTextInput += AssociatedObjectPreviewTextInput; AssociatedObject.PreviewKeyDown += AssociatedObjectPreviewKeyDown; DataObject.AddPastingHandler(AssociatedObject, Pasting); } protected override void OnDetaching() { base.OnDetaching(); AssociatedObject.PreviewTextInput -= AssociatedObjectPreviewTextInput; AssociatedObject.PreviewKeyDown -= AssociatedObjectPreviewKeyDown; DataObject.RemovePastingHandler(AssociatedObject, Pasting); } private void Pasting(object sender, DataObjectPastingEventArgs e) { if (e.DataObject.GetDataPresent(typeof(string))) { var pastedText = (string)e.DataObject.GetData(typeof(string)); if(!this.IsValidInput(this.GetText(pastedText))) { System.Media.SystemSounds.Beep.Play(); e.CancelCommand(); } } else { System.Media.SystemSounds.Beep.Play(); e.CancelCommand(); } } private void AssociatedObjectPreviewKeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.Space) { if (!this.IsValidInput(this.GetText(" "))) { System.Media.SystemSounds.Beep.Play(); e.Handled = true; } } } private void AssociatedObjectPreviewTextInput(object sender, TextCompositionEventArgs e) { if (!this.IsValidInput(this.GetText(e.Text))) { System.Media.SystemSounds.Beep.Play(); e.Handled = true; } } private string GetText(string input) { var txt = this.AssociatedObject; var realtext = txt.Text.Remove(txt.SelectionStart, txt.SelectionLength); var newtext = realtext.Insert(txt.CaretIndex, input); return newtext; } private bool IsValidInput(string input) { switch (InputMode) { case TextBoxInputMode.None: return true; case TextBoxInputMode.DigitInput: return input.CheckIsDigit(); case TextBoxInputMode.DecimalInput: //minus einmal am anfang zulässig if (input == "-") return true; decimal d; return decimal.TryParse(input, out d); default: throw new ArgumentException("Unknown TextBoxInputMode"); } return true; } } public enum TextBoxInputMode { None, DecimalInput, DigitInput }
using
<TextBox> <i:Interaction.Behaviors> <MyBehaviors:TextBoxInputBehavior InputMode="DecimalInput"/> </i:Interaction.Behaviors> </TextBox>