详细说明我留下的评论,这是一个如何完成的示例。
仅供参考,我使用 nuget 包 MvvmLight 进行管道。
MainWindow.xaml
<StackPanel>
<TextBox x:Name="myTextBox" Text="{Binding SomeNumberViewModel.IntermediateText, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" Width="100" Margin="5"/>
<Button Content="Hi" HorizontalAlignment="Center" Padding="5,15" Margin="5"/>
</StackPanel>
MainWindow.xaml.cs
public MainViewModel ViewModel
{
get
{
return this.DataContext as MainViewModel;
}
}
public MainWindow()
{
InitializeComponent();
this.myTextBox.LostFocus += MyTextBox_LostFocus;
}
private void MyTextBox_LostFocus(object sender, RoutedEventArgs e)
{
// If the IntermediateText has no validation errors, then update your model.
if (string.IsNullOrEmpty(this.ViewModel.SomeNumberViewModel[nameof(this.ViewModel.SomeNumberViewModel.IntermediateText)]))
{
// Update your model and it gets formatted result
this.ViewModel.SomeNumberViewModel.ModelValue = this.ViewModel.SomeNumberViewModel.IntermediateText;
// Then, update your IntermediateText to update the UI.
this.ViewModel.SomeNumberViewModel.IntermediateText = this.ViewModel.SomeNumberViewModel.ModelValue;
}
}
MainViewModel.cs
public class MainViewModel : ViewModelBase
{
private SomeNumberViewModel someNumberViewModel;
public string MyTitle { get => "Stack Overflow Question 65279367"; }
public SomeNumberViewModel SomeNumberViewModel
{
get
{
if (this.someNumberViewModel == null)
this.someNumberViewModel = new SomeNumberViewModel(new MyModel());
return this.someNumberViewModel;
}
}
}
SomeNumberViewModel.cs
public class SomeNumberViewModel : ViewModelBase, IDataErrorInfo
{
public SomeNumberViewModel(MyModel model)
{
this.Model = model;
}
private string intermediateText;
public string IntermediateText { get => this.intermediateText; set { this.intermediateText = value; RaisePropertyChanged(); } }
public string ModelValue
{
get => this.Model.SomeNumber.ToString("0.00");
set
{
try
{
this.Model.SomeNumber = Convert.ToDouble(value);
RaisePropertyChanged();
}
catch
{
}
}
}
public MyModel Model { get; private set; }
public string Error { get => null; }
public string this[string columnName]
{
get
{
switch (columnName)
{
case "IntermediateText":
if (!string.IsNullOrEmpty(this.IntermediateText) && FormatErrors(this.IntermediateText))
return "Format errors";
break;
}
return string.Empty;
}
}
/// <summary>
/// Only allow numbers to be \d+, or \d+\.\d+
/// For Example: 1, 1.0, 11.23, etc.
/// Anything else is a format violation.
/// </summary>
/// <param name="numberText"></param>
/// <returns></returns>
private bool FormatErrors(string numberText)
{
var valid = (Regex.IsMatch(numberText, @"^(\d+|\d+\.\d+)$"));
return !valid;
}
}
MyModel.cs
public class MyModel
{
public double SomeNumber { get; set; }
}