问题
I recently got a requirement that all the textboxes in my application should automatically trim the text when leaving the textbox. I can't/don't want to do this by adding converters or events to every single textbox, or by writing/rewriting the properties in my viewmodel for every single binding. First, it will be very messy and repetetive, second, I already have converters for many of my textboxes, and afaik, you can't connect multiple converters without writing a multiconverter.
Since you can't apply the trim at every key stroke, the trim must occur after the unfocus event but before the binding operation to my viewmodel.
What is the best way of doing this? Writing my own textbox class? Some kind of controltemplate/triggers? I'm not familiar enough with those options to know which path will be easiest.
I already have a style set up in App.xaml for all my textboxes which makes them look like IsEnabled=false when IsReadOnly is set to true, so that might complicate things.
回答1:
The MVVM way would be using Behaviors:
using System.Windows.Controls;
using System.Windows.Interactivity;
public class TrimTextBoxBehavior : Behavior<TextBox>
{
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.LostFocus += AssociatedObject_LostFocus;
}
private void AssociatedObject_LostFocus(object sender, System.Windows.RoutedEventArgs e)
{
AssociatedObject.Text = AssociatedObject.Text.Trim();
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.LostFocus -= AssociatedObject_LostFocus;
}
}
Then in your XAML:
<UserControl ...
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:local="clr-namespace:Your.Namespace;assembly=Your.Assembly">
<TextBox>
<i:Interaction.Behaviors>
<local:TrimTextBoxBehavior />
</i:Interaction.Behaviors>
</TextBox>
Notice that you need to replaceYour.Namespace
and Your.Assembly
in the local
XML namespace declaration. Also, you need to add System.Windows.Interactivy to your project.
回答2:
Ok so I got a good solution working, here's my very simple solution:
I added my own control which inherits from TextBox, TrimmedTextBox. Constructor:
public TrimmedTextBox()
{
InitializeComponent();
LostFocus += TrimmedTextBox_LostFocus;
}
private void TrimmedTextBox_LostFocus(object sender, RoutedEventArgs e)
{
Text = Text.Trim();
}
This is triggered before the binding does it's job, so what's saved to my properties are actually the trimmed value.
I also had to add modifications in all styles where TargetType=TextBox of course.
来源:https://stackoverflow.com/questions/33890727/wpf-trim-all-textboxes