在WPF中的数值数据输入
在WPF中的数值数据输入
在WPF应用程序中,您是如何处理数值输入的?
由于没有NumericUpDown控件,我一直在使用TextBox,并通过下面的代码处理其PreviewKeyDown事件,但是这样做相当丑陋。
有人找到了更优雅的方法来从用户那里获取数值数据,而不依赖于第三方控件吗?
private void NumericEditPreviewKeyDown(object sender, KeyEventArgs e) { bool isNumPadNumeric = (e.Key >= Key.NumPad0 && e.Key <= Key.NumPad9) || e.Key == Key.Decimal; bool isNumeric = (e.Key >= Key.D0 && e.Key <= Key.D9) || e.Key == Key.OemPeriod; if ((isNumeric || isNumPadNumeric) && Keyboard.Modifiers != ModifierKeys.None) { e.Handled = true; return; } bool isControl = ((Keyboard.Modifiers != ModifierKeys.None && Keyboard.Modifiers != ModifierKeys.Shift) || e.Key == Key.Back || e.Key == Key.Delete || e.Key == Key.Insert || e.Key == Key.Down || e.Key == Key.Left || e.Key == Key.Right || e.Key == Key.Up || e.Key == Key.Tab || e.Key == Key.PageDown || e.Key == Key.PageUp || e.Key == Key.Enter || e.Key == Key.Return || e.Key == Key.Escape || e.Key == Key.Home || e.Key == Key.End); e.Handled = !isControl && !isNumeric && !isNumPadNumeric; }
问题的出现原因:
该问题的出现是因为需要在WPF中实现数字数据输入,并且需要使用上下箭头来改变文本框中的值。作者使用了一个附加属性来实现这个功能,但这并没有解决验证问题,只是解决了没有数字上下控件时的问题。
解决方法:
为了解决这个问题,作者提供了一个附加属性TextBoxNumbers.SingleDelta,可以通过在XAML中使用该属性来实现数字数据输入。代码实现了以下功能:
- 使用上下箭头来增加或减少值
- 使用Shift + 上下箭头来以较大的步长增加或减少值
- 使用Page Up和Page Down键来以更大的步长增加或减少值
- 绑定文本属性的转换器
代码如下:
using System; using System.Collections.Generic; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Input; namespace Helpers { public class TextBoxNumbers { public static Decimal GetSingleDelta(DependencyObject obj) { return (Decimal)obj.GetValue(SingleDeltaProperty); } public static void SetSingleDelta(DependencyObject obj, Decimal value) { obj.SetValue(SingleDeltaProperty, value); } public static readonly DependencyProperty SingleDeltaProperty = DependencyProperty.RegisterAttached("SingleDelta", typeof(Decimal), typeof(TextBoxNumbers), new UIPropertyMetadata(0.0m, new PropertyChangedCallback(f))); public static void f(DependencyObject o, DependencyPropertyChangedEventArgs e) { TextBox t = o as TextBox; if (t == null) return; t.PreviewKeyDown += new System.Windows.Input.KeyEventHandler(t_PreviewKeyDown); } private static Decimal GetSingleValue(DependencyObject obj) { return GetSingleDelta(obj); } private static Decimal GetDoubleValue(DependencyObject obj) { return GetSingleValue(obj) * 10; } private static Decimal GetTripleValue(DependencyObject obj) { return GetSingleValue(obj) * 100; } static void t_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e) { TextBox t = sender as TextBox; Decimal i; if (t == null) return; if (!Decimal.TryParse(t.Text, out i)) return; switch (e.Key) { case System.Windows.Input.Key.Up: if (Keyboard.Modifiers == ModifierKeys.Shift) i += GetDoubleValue(t); else i += GetSingleValue(t); break; case System.Windows.Input.Key.Down: if (Keyboard.Modifiers == ModifierKeys.Shift) i -= GetDoubleValue(t); else i -= GetSingleValue(t); break; case System.Windows.Input.Key.PageUp: i += GetTripleValue(t); break; case System.Windows.Input.Key.PageDown: i -= GetTripleValue(t); break; default: return; } if (BindingOperations.IsDataBound(t, TextBox.TextProperty)) { try { Binding binding = BindingOperations.GetBinding(t, TextBox.TextProperty); t.Text = (string)binding.Converter.Convert(i, null, binding.ConverterParameter, binding.ConverterCulture); } catch { t.Text = i.ToString(); } } else t.Text = i.ToString(); } } }
以上代码提供了一种在WPF中实现数字数据输入的方法,并解决了验证问题。
在WPF中进行数字数据输入时,有一个问题出现。问题的原因是用户可以输入非数字字符,这可能导致数据不正确。为了解决这个问题,可以使用以下代码:
protected override void OnPreviewTextInput(System.Windows.Input.TextCompositionEventArgs e)
{
e.Handled = !AreAllValidNumericChars(e.Text);
base.OnPreviewTextInput(e);
}
private bool AreAllValidNumericChars(string str)
{
foreach(char c in str)
{
if(!Char.IsNumber(c)) return false;
}
return true;
}
这段代码在`OnPreviewTextInput`方法中进行处理。它将检查输入的文本是否只包含数字字符,如果不是,则设置`e.Handled`为`true`,这将阻止非数字字符输入。这种方法比其他方法更简洁,并且仍然允许使用控制键(如箭头键和退格键)。
然而,这种方法有一些限制。它无法阻止用户粘贴非数字字符到控件中。但是,目前来说这并不是一个大问题。如果需要处理粘贴非数字数据的情况,可以参考juanagui的答案(链接:http://stackoverflow.com/a/2673131/755404)。
此外,这段代码还存在一些其他问题。它无法处理小数和负数。如果用户输入了多个小数点或负号,代码将返回错误结果。不过,这些问题可以很容易地修复。可以使用以下代码来解决这些问题:
e.Handled = !e.Text.ToCharArray().All(c => Char.IsNumber(c));
或者
e.Handled = !e.Text.All(Char.IsNumber);
以上是解决WPF中数字数据输入的问题的方法和注意事项。希望对你有所帮助!