WPF:将文本框输入格式化为用户类型

时间:2017-01-16 10:11:41

标签: c# wpf xaml mvvm

在我们的WPF应用程序中,有几个文本框,用户应该只输入货币。强制文本框在输入时格式化输入:

<TextBox Text="{Binding CostOut, StringFormat='{}{0:C}' />

然而,这种格式如此之快以至于它会导致用户意外的效果,因为文本是类型,因为小数点前后的数字似乎几乎被视为单独的字段。

为了解决这个问题,我们添加了延迟:

<TextBox Text="{Binding CostOut, StringFormat='{}{0:C}', Delay=1000  />

由于大多数人在数字格式化之前完成了打字,因此效果更好。但是,应用程序很复杂并且处理重要的财务数据,并且一些用户在输入数字时仔细考虑这些数字。对于这些慢速打字机,这种延迟仍然导致他们的输入被重新格式化为中型。

我不愿意在“延迟”路线上走得更远,因为我们最终会在某人保存之前达到没有格式化的程度。我发现并尝试了一个WPF CurrencyTextBox作为解决方案被拒绝,因为“收银机”式打字太不熟悉了。

目前建议的解决方案是从应用程序中删除所有格式,并仅在保存时格式化。这对我来说很激动,我不禁想知道是否有更好的解决方案?

3 个答案:

答案 0 :(得分:3)

当textBox失去对文本框的LostFocus事件的关注时,您可以尝试设置所需的格式。它允许用户输入他/她必须的时间,并且不会像在保存按钮上格式化那样激烈。

答案 1 :(得分:3)

正如评论中所提到的,我创建了一个关于如何将LostFocus-Event绑定到ViewModel中的ICommand - 属性的小例子。

附属物看起来像:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace TextBoxLostFocusBehaviorExample
{
    internal static class TextBoxExtensions
    {
        public static readonly DependencyProperty LostFocusCommandProperty = DependencyProperty.RegisterAttached(
            "LostFocusCommand",
            typeof(ICommand),
            typeof(TextBoxExtensions),
            new PropertyMetadata(default(ICommand), OnLostFocusCommandChanged));

        private static void OnLostFocusCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            TextBox textBox = d as TextBox;
            if (textBox == null)
            {
                return;
            }

            if (e.NewValue != null)
            {
                textBox.LostFocus += TextBoxOnLostFocus;
            }
        }

        private static void TextBoxOnLostFocus(object sender, RoutedEventArgs e)
        {
            TextBox textBox = sender as TextBox;
            if (textBox == null)
            {
                return;
            }

            ICommand command = GetLostFocusCommand(textBox);
            command.Execute(null);
        }

        public static void SetLostFocusCommand(DependencyObject element, ICommand value)
        {
            element.SetValue(LostFocusCommandProperty, value);
        }

        public static ICommand GetLostFocusCommand(DependencyObject element)
        {
            return (ICommand)element.GetValue(LostFocusCommandProperty);
        }
    }
}

在ViewModel中,您有一个ICommand类型的属性,它看起来像:

private ICommand lostFocusCommand;
public ICommand LostFocusCommand
{
    get { return lostFocusCommand ?? (lostFocusCommand = new RelayCommand(p => CostOutLostFocus())); }
}

CostOutLostFocus - 事件被触发时,LostFocus - 方法将被调用。

视图中附加属性的用法如下所示:

<TextBox Text="{Binding CostOut, Mode=TwoWay}" TextBoxLostFocusBehaviorExample:TextBoxExtensions.LostFocusCommand="{Binding LostFocusCommand}"/>

TextBoxLostFocusBehaviorExample是定义附加属性的class的命名空间。

答案 2 :(得分:1)

  

目前建议的解决方案是从应用程序中删除所有格式,并仅在保存时格式化。这对我来说很激动,我不知道是否有更好的解决方案?

您可以更新源属性并在用户走出TextBox时应用格式,只需在XAML标记中将绑定的UpdateSourceTrigger属性设置为其默认值LostFocus:

<TextBox Text="{Binding CostOut, StringFormat={}{0:C}, UpdateSourceTrigger=LostFocus}" />

这至少应该比保存时应用格式更好一些。

另一个选择是使用某种蒙版TextBox。没有内置的,但您可以尝试开源的Extended WPF Toolkit中提供的那个:https://wpftoolkit.codeplex.com/wikipage?title=MaskedTextBox&referringTitle=Home

还有商业选项:http://docs.telerik.com/devtools/wpf/controls/radmaskedinput/features/maskedinput-controls/currency