<TextBox> <i:Interaction.Behaviors> <Behaviors:TextBoxInputBehavior InputMode="DigitInput" /> </i:Interaction.Behaviors> </TextBox>
Und hier der Code dazu:
public class TextBoxInputBehavior : Behavior<TextBox> { const NumberStyles validNumberStyles = NumberStyles.AllowDecimalPoint | NumberStyles.AllowThousands | NumberStyles.AllowLeadingSign; public TextBoxInputBehavior() { this.InputMode = TextBoxInputMode.None; this.JustPositivDecimalInput = false; this.MaxVorkommastellen = null; } public TextBoxInputMode InputMode { get; set; } public ushort? MaxVorkommastellen { get; set; } public static readonly DependencyProperty JustPositivDecimalInputProperty = DependencyProperty.Register("JustPositivDecimalInput", typeof(bool), typeof(TextBoxInputBehavior), new FrameworkPropertyMetadata(false)); public bool JustPositivDecimalInput { get { return (bool)GetValue(JustPositivDecimalInputProperty); } set { SetValue(JustPositivDecimalInputProperty, value); } } 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; } } if (e.Key == Key.Back) { //wenn was selektiert wird dann wird nur das gelöscht mit BACK if (this.AssociatedObject.SelectionLength > 0) { if (!this.IsValidInput(this.GetText(""))) { System.Media.SystemSounds.Beep.Play(); e.Handled = true; } } else if(this.AssociatedObject.CaretIndex > 0) { //selber löschen var txt = this.AssociatedObject.Text; var backspace = txt.Remove(this.AssociatedObject.CaretIndex - 1, 1); if (!this.IsValidInput(backspace)) { System.Media.SystemSounds.Beep.Play(); e.Handled = true; } } } if (e.Key == Key.Delete) { //wenn was selektiert wird dann wird nur das gelöscht mit ENTF if (this.AssociatedObject.SelectionLength > 0) { if (!this.IsValidInput(this.GetText(""))) { System.Media.SystemSounds.Beep.Play(); e.Handled = true; } } else if (this.AssociatedObject.CaretIndex < this.AssociatedObject.Text.Length) { //selber löschen var txt = this.AssociatedObject.Text; var entf = txt.Remove(this.AssociatedObject.CaretIndex, 1); if (!this.IsValidInput(entf)) { 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; int selectionStart = txt.SelectionStart; if (txt.Text.Length < selectionStart) selectionStart = txt.Text.Length; int selectionLength = txt.SelectionLength; if (txt.Text.Length < selectionStart + selectionLength) selectionLength = txt.Text.Length - selectionStart; var realtext = txt.Text.Remove(selectionStart, selectionLength); int caretIndex = txt.CaretIndex; if (realtext.Length < caretIndex) caretIndex = realtext.Length; var newtext = realtext.Insert(caretIndex, input); return newtext; } private bool IsValidInput(string input) { if (input.Length == 0) return true; switch (InputMode) { case TextBoxInputMode.None: return true; case TextBoxInputMode.DigitInput: return CheckIsDigit(input); case TextBoxInputMode.DecimalInput: decimal d; //wen mehr als ein Komma if (input.ToCharArray().Where(x => x == ',').Count() > 1) return false; if (input.Contains("-")) { if (this.JustPositivDecimalInput) return false; if (input.IndexOf("-",StringComparison.Ordinal) > 0) return false; if(input.ToCharArray().Count(x=>x=='-') > 1) return false; //minus einmal am anfang zulässig if (input.Length == 1) return true; } var result = decimal.TryParse(input, validNumberStyles, CultureInfo.CurrentCulture, out d); return result; case TextBoxInputMode.PercentInput: //99,999 is zulässig und nur positiv ohne 1000er Trennzeichen float f; if (input.Contains("-")) return false; //wen mehr als ein Komma if (input.ToCharArray().Where(x => x == ',').Count() > 1) return false; var percentResult = float.TryParse(input, NumberStyles.Float, CultureInfo.CurrentCulture, out f); if (MaxVorkommastellen.HasValue) { var vorkomma = Math.Truncate(f); if (vorkomma.ToString(CultureInfo.CurrentCulture).Length > MaxVorkommastellen.Value) return false; } return percentResult; default: throw new ArgumentException("Unknown TextBoxInputMode"); } return true; } private bool CheckIsDigit(string wert) { return wert.ToCharArray().All(Char.IsDigit); } } public enum TextBoxInputMode { None, DecimalInput, DigitInput, PercentInput }