Hier mal ein nettes Behavior was ich recht häufig benutze, um Eingaben in einer TextBox zu beschränken. Die Anwendung ist ganz einfach:
<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
}