我有一个文本框,其Text属性有一个TwoWay MultiBinding,其中UpdateSourceTrigger设置为PropertyChanged。第一个Binding是一个依赖属性 ( Value ),它有一个PropertyChangedCallBack函数,该函数将值四舍五入到小数点后一位。
文本框的目的是在用户键入时执行舍入,而不是在文本框失去焦点时执行舍入,因此UpdateSourceTrigger设置为PropertyChanged。
我遇到的问题是,如果输入的文本不会导致值更改,则文本属性和值会不同步。只有当舍入操作导致Value发生变化时, Text才会即时更新。例如,如果Text和Value都是 123.4 并且用户在此之后键入 1,则Value将四舍五入为相同的值 (123.4),但Text显示 123.41。但是,如果在 4 之后键入 9,则Value向上舍入为 123.5。并且由于这种实际变化,文本随后更新为相同的 (123.5)。
即使自上次触发以来源没有更改,是否有任何方法可以强制文本框从其源更新?我尝试过使用BindingExpressionBase.UpdateTarget()
,但这仅在UpdateSourceTrigger设置为Explicit时有效,因为在可以调用UpdateTarget的合适时间(例如TextInput处理程序)之前不再更新Value,因此无法使用。我尝试了其他方法,例如从绑定的Value中显式更新Text值,暂时强制对Value进行实际更改以调用更新,但是这些“黑客”要么不起作用,要么导致其他问题。
任何帮助将不胜感激。
代码如下。
XAML 片段
<TextBox>
<TextBox.Text>
<MultiBinding Converter="{local:NumberFormatConverter}"
UpdateSourceTrigger="Explicit"
Mode="TwoWay">
<Binding Path="Value"
RelativeSource="{RelativeSource AncestorType={x:Type Window}}"
Mode="TwoWay" />
</MultiBinding>
</TextBox.Text>
</TextBox>
C# 片段
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register(
"Value", typeof(decimal), typeof(MainWindow),
new FrameworkPropertyMetadata(0m,
new PropertyChangedCallback(OnValueChanged)));
private static void OnValueChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
{
obj.SetValue(ValueProperty, Math.Round((decimal)args.NewValue, 1));
}
需要转换器类
public class NumberFormatConverter : MarkupExtension, IMultiValueConverter
{
public static NumberFormatConverter Instance { private set; get; }
static NumberFormatConverter()
{
Instance = new NumberFormatConverter();
}
public override object ProvideValue(IServiceProvider serviceProvider_)
{
return Instance;
}
#region Implementation of IMultiValueConverter
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
return values[0].ToString();
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
var result = 0m;
if (value != null)
{
decimal.TryParse(value.ToString(), out result);
}
return new object[] { result };
}
#endregion
}