WPF:将文本框输入格式化为用户类型(WPF: formatting textbox input as user types)

编程入门 行业动态 更新时间:2024-10-26 14:32:20
WPF:将文本框输入格式化为用户类型(WPF: formatting textbox input as user types)

在我们的WPF应用程序中,有几个文本框,用户应该只输入货币。 很容易强制文本框对输入进行格式化,如下所示:

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

但是,这种格式的格式如此之快,以至于会导致用户意想不到的效果,因为文本是类型的,因为小数前后的数字看起来几乎被视为单独的字段。

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

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

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

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

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

In our WPF application, there are several textboxes where users ought to input only currency. It's easy to force the textbox to format the input as it goes in:

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

However, this formats so quickly that it causes unexpected effects to the user as the text is type, because the numbers before and after the decimal seem to be treated almost as separate fields.

To counter this, we added a delay:

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

Which worked better as most people had finished typing before their numbers got formatted. However, the application is complex and deals with important financial data, and some users think carefully about the numbers as they're typed. For these slow typers, this delay still caused their input to get reformatted mid-type.

I'm unwilling to go further down the "delay" route as we'll eventually get to a point where it doesn't get formatted before someone saves. I found and tried a WPF CurrencyTextBox which was rejected as a solution because the "cash register" style typing was too unfamiliar.

Currently the proposed solution is to remove all formatting from the application and format only on save. This feels drastic to me, and I can't help wondering if there's a better solution?

最满意答案

正如在评论中提到的,我已经创建了一个关于如何将LostFocus事件绑定到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())); } }

当LostFocus -Event被触发时, CostOutLostFocus将被调用。

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

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

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

As mentioned in a comment I've created a small example on how to bind the LostFocus-Event to a ICommand-property in your ViewModel.

The attached-property looks like:

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); } } }

In your ViewModel you then have a property of type ICommand which can look like:

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

And the CostOutLostFocus-Method will be called when the LostFocus-Event is triggered.

The usage of the attached property in the view looks like:

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

TextBoxLostFocusBehaviorExample is the namespace where the class of the attached property is defined.

更多推荐

本文发布于:2023-08-01 11:30:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1358104.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:文本框   类型   格式   用户   WPF

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!