C# WPF:将文本框输入格式化为用户类型
在我们的WPF应用程序中,有几个文本框,用户应该只在其中输入货币。很容易强制文本框在输入时格式化输入:C# WPF:将文本框输入格式化为用户类型,c#,wpf,xaml,mvvm,C#,Wpf,Xaml,Mvvm,在我们的WPF应用程序中,有几个文本框,用户应该只在其中输入货币。很容易强制文本框在输入时格式化输入: <TextBox Text="{Binding CostOut, StringFormat='{}{0:C}' /> 因为大多数人在数字格式化之前就已经完成了打字,所以这种方法效果更好。然而,这个应用程序很复杂,需要处理重要的财务数据,一些用户在键入数字时会仔细考虑。对于这些速度较慢的打字机,这种延迟仍然会导致它们的输入被重新格式化 我不愿意在“延迟”的路线上走得更远,因为我
<TextBox Text="{Binding CostOut, StringFormat='{}{0:C}' />
因为大多数人在数字格式化之前就已经完成了打字,所以这种方法效果更好。然而,这个应用程序很复杂,需要处理重要的财务数据,一些用户在键入数字时会仔细考虑。对于这些速度较慢的打字机,这种延迟仍然会导致它们的输入被重新格式化
我不愿意在“延迟”的路线上走得更远,因为我们最终会到达一个点,在有人保存之前,它不会被格式化。我找到并尝试了一个WPF CurrencyTextBox,但由于“收银机”样式的键入太不熟悉而被拒绝作为解决方案
目前建议的解决方案是从应用程序中删除所有格式,并仅在保存时格式化。这让我感觉很激烈,我不禁想知道是否有更好的解决方案?当文本框在文本框的
LostFocus
事件上失去焦点时,您可以尝试设置所需的格式。它将允许用户键入他/她必须键入的内容,并且不会像在“保存”按钮上设置格式那样激烈。当文本框在文本框的LostFocus
事件上失去焦点时,您可以尝试设置所需的格式。这将允许用户键入他/她必须键入的内容,并且不会像在“保存”按钮上设置格式那样激烈
目前建议的解决方案是从应用程序中删除所有格式,并仅在保存时格式化。这让我感觉很激烈,我不禁想知道是否有更好的解决方案
当用户跳出文本框时,只需将绑定的UpdateSourceTrigger属性设置为XAML标记中的默认值LostFocus,即可更新源属性并应用格式:
<TextBox Text="{Binding CostOut, StringFormat={}{0:C}, UpdateSourceTrigger=LostFocus}" />
这至少比保存时应用格式要好一点
另一种选择是使用某种蒙面文本框。没有内置的工具,但您可以尝试开源扩展WPF工具包中提供的工具:
也有商业选择:
目前建议的解决方案是从应用程序中删除所有格式,并仅在保存时格式化。这让我感觉很激烈,我不禁想知道是否有更好的解决方案
当用户跳出文本框时,只需将绑定的UpdateSourceTrigger属性设置为XAML标记中的默认值LostFocus,即可更新源属性并应用格式:
<TextBox Text="{Binding CostOut, StringFormat={}{0:C}, UpdateSourceTrigger=LostFocus}" />
这至少比保存时应用格式要好一点
另一种选择是使用某种蒙面文本框。没有内置的工具,但您可以尝试开源扩展WPF工具包中提供的工具:
还有一些商业选项可用:如一条评论中所述,我创建了一个小示例,介绍如何将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);
}
}
}
<TextBox Text="{Binding CostOut, Mode=TwoWay}" TextBoxLostFocusBehaviorExample:TextBoxExtensions.LostFocusCommand="{Binding LostFocusCommand}"/>
然后,在ViewModel中有一个类型为ICommand
的属性,该属性可以如下所示:
private ICommand lostFocusCommand;
public ICommand LostFocusCommand
{
get { return lostFocusCommand ?? (lostFocusCommand = new RelayCommand(p => CostOutLostFocus())); }
}
当触发LostFocus
-事件时,将调用CostOutLostFocus
-方法
视图中附加属性的用法如下所示:
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);
}
}
}
<TextBox Text="{Binding CostOut, Mode=TwoWay}" TextBoxLostFocusBehaviorExample:TextBoxExtensions.LostFocusCommand="{Binding LostFocusCommand}"/>
TextBoxLostFocusBehaviorExample是定义附加属性的
类的名称空间。如注释中所述,我创建了一个小示例,介绍如何将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);
}
}
}
<TextBox Text="{Binding CostOut, Mode=TwoWay}" TextBoxLostFocusBehaviorExample:TextBoxExtensions.LostFocusCommand="{Binding LostFocusCommand}"/>
然后,在ViewModel中有一个类型为ICommand
的属性,该属性可以如下所示:
private ICommand lostFocusCommand;
public ICommand LostFocusCommand
{
get { return lostFocusCommand ?? (lostFocusCommand = new RelayCommand(p => CostOutLostFocus())); }
}
当触发LostFocus
-事件时,将调用CostOutLostFocus
-方法
视图中附加属性的用法如下所示:
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);
}
}
}
<TextBox Text="{Binding CostOut, Mode=TwoWay}" TextBoxLostFocusBehaviorExample:TextBoxExtensions.LostFocusCommand="{Binding LostFocusCommand}"/>
TextBoxLostFocusBehaviorExample是用于定义附加属性的类的命名空间。您使用的.net framework版本是什么?我认为在第四节中有一些问题。0@Pikoh这是4.5我想行为会做得更好。尝试从@WillP answer使用您正在使用的.net framework版本?我认为在第四节中有一些问题。0@Pikoh这是4.5我想行为会做得更好。尝试使用@WillP answer,如果您想知道如何在不破坏MVVM模式的情况下获得该事件,请告诉我。然后我为您写一个小的附加属性。@Tomtom这会很有帮助,谢谢-这就是我最初没有走这条路线的原因。如果您想知道如何在不破坏MVVM模式的情况下获得该事件,请告诉我。然后我给你写一个小的附加属性。@Tomtom那会很有帮助的,谢谢-这就是我当初没有走这条路的原因