每次值发生变化时,您都会更新您的属性。当您输入
.
时,它会被写入您的视图模型中并更新视图。
例如如果您输入
100.
,它会四舍五入为 100
,因此您永远不会看到任何点。
您有一些选项可以改变此行为:
使用延迟绑定:
<TextBox Text="{Binding Path=TransactionDetails.TransactionAmount,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged,
Delay=250}"
Grid.Column="3"
Grid.ColumnSpan="2"
Grid.Row="5"
x:Name="TextBoxAmount" />
仅在与保存的值不同时更改该值 (我建议每个绑定都使用这个):
private double _transactionAmount;
public double TransactionAmount
{
get { return _transactionAmount; }
set
{
if (_transactionAmount != value)
{
_transactionAmount = value;
Notify("TransactionAmount");
}
}
或使用某种验证,例如验证异常。
当您的应用程序面向 .NET 4.0 或更早版本时,该行为符合预期,但后来发生了更改 (MSDN)。可以通过设置恢复旧的行为:
System.Windows.FrameworkCompatibilityPreferences.KeepTextBoxDisplaySynchronizedWithTextProperty = false;
尽早设置(例如在 App.cs 的构造函数中),否则框架会引发异常。
来源及详细解释:https://web.archive.org/web/20220127083119/https://www.mobilemotion.eu/?p=1855
我通过使用
StringFormat
像得到的最佳解决方案
<TextBox Text="{Binding TransactionDetails.TransactionAmount, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged,StringFormat=N2}" Grid.Column="3"
Grid.ColumnSpan="2" Grid.Row="5" x:Name="TextBoxAmount" />
我们也可以根据要求定制字符串格式
您的问题出在 UpdateSourceTrigger 上。 你可以使用这样的东西,而不是在那里使用,
private double amount;
public double Amount
{
get
{
return amount;
}
set
{
amount= value;
PropertyChanged();
Calculation();
}
}
PropertyChanged() 您将从 INotifyPropertyChanged 中获取它。欲了解更多信息,请点击此处 https://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged(v=vs.110).aspx
绑定双精度类型源数据时,可以用此类替换默认转换器。这样使用起来比较方便。下面是代码:
public class double2txtConverter : IValueConverter
{
string _strCache;
double _dCache;
//Convert double to string of textbox.
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (_dCache == (double)value)
return _strCache;
else
return value.ToString();
}
//convert string to double;
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
_strCache = (string)value;
_dCache = double.Parse(_strCache);
return _dCache;
}
}
//below is codebehind usage:
Binding bd = new Binding(path);
bd.Converter = new double2txtConverter();
bd.Source = source;
bd.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
txtTarget.SetBinding(TextBox.TextProperty, bd);
我根据上面Herm的回答给出答案。解释是正确的,但在控制上使用
Delay
并不能完全解决问题。如果最终用户输入0.005,则需要的延迟会更多,否则它将重新写入值为0。
相反,使用字符串属性进行绑定并尝试将其解析为双倍,并根据解析输出设置您需要的 long 值。在设置值之前进行您需要的所有类型的验证
private double _amount;
private string _amountString;
public string Amount
{
get { return _amountString;}
set {
double d=0;
if(Double.TryParse(value, out d))
{
_amountString=value;
_amount=d;
}
}
}
}
在属性使用的绑定中,
UpdateSourceTrigger=LostFocus
。一旦文本框失去焦点,它将更新属性。
我通过附加属性解决了这个问题。
public class DoubleTextBox : TextBox
{
public string DoubleText
{
get => (string)GetValue(DoubleTextProperty);
set => SetValue(DoubleTextProperty, value);
}
public static readonly DependencyProperty DoubleTextProperty =
DependencyProperty.Register(
nameof(DoubleText),
typeof(string),
typeof(DoubleTextBox),
new FrameworkPropertyMetadata(
string.Empty,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault | FrameworkPropertyMetadataOptions.Journal,
new PropertyChangedCallback(OnDoubleTextChanged),
null,
true,
UpdateSourceTrigger.LostFocus));
private static void OnDoubleTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is TextBox textBox)
{
var currentText = textBox.Text;
var newText = (string)e.NewValue;
if (currentText == newText)
return;
if (
double.TryParse(currentText, out var currentDouble) &&
double.TryParse(newText, out var newDouble) &&
currentDouble == newDouble
)
return;
textBox.Text = newText;
}
}
protected override void OnTextChanged(TextChangedEventArgs e)
{
base.OnTextChanged(e);
this.DoubleText = this.Text;
}
}
用途:
<myControl:DoubleTextBox DoubleText="{Binding Double1, UpdateSourceTrigger=PropertyChanged}" />