我想做的很简单,当 TextBox 有焦点时显示一种格式,而在没有焦点时显示另一种格式。在我的情况下,我在不集中时将一个数字四舍五入为 3 位数字,但在集中于编辑时显示实际的整数。
我有一个使用多重绑定的相当简单的解决方案,我觉得我快到了。一切都按预期工作,即时窗口中没有错误,但绑定不会更新源。
我正在使用这种样式来传递我的绑定以及 TextBox 是否将焦点传递给转换器。
<Style x:Key="RoundedTextBox" TargetType="{x:Type ContentControl}">
<Setter Property="Focusable" Value="False"/>
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBox x:Name="TB" TextAlignment="Right" DataContext="{TemplateBinding Content}">
<TextBox.Text>
<MultiBinding Converter="{StaticResource DecRounder}" UpdateSourceTrigger="PropertyChanged">
<MultiBinding.Bindings>
<Binding ElementName="TB" Path="DataContext" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged" BindsDirectlyToSource="True" />
<Binding ElementName="TB" Path="IsFocused" Mode="OneWay" />
</MultiBinding.Bindings>
</MultiBinding>
</TextBox.Text>
</TextBox>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
示例用法:
<ContentControl Style="{StaticResource RoundedTextBox}"
Content="{Binding Path=Model.SomeNumber}" />
多值转换器就在这里。
public class DecimalRoundingConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (values.Length != 2)
throw new Exception("Invalid number of values for DecimalRoundingConverter!");
if (values[0] is string)
return values[0];
if (values[0] != null && !(values[0] is decimal))
throw new Exception("Invalid type for first value used with DecimalRoundingConverter!");
if (!(values[1] is bool))
throw new Exception("Invalid type for second value used with DecimalRoundingConverter!");
if (targetType != typeof(string))
throw new Exception("Invalid target type used with DecimalRoundingConverter!");
if (values[0] == null)
return null;
decimal number = (decimal)values[0];
bool isFocused;
if (values[1] == null)
isFocused = true;
else if (values[1] is bool)
isFocused = (bool)values[1];
else
if (!bool.TryParse((string)values[1], out isFocused))
throw new Exception("Invalid converter parameter used with DecimalRoundingConverter!");
return string.Format(isFocused ? "{0:.#############################}" : "{0:.###}", number);
}
public object[] ConvertBack(object value, Type[] targetType, object parameter, System.Globalization.CultureInfo culture)
{
decimal d;
var ret = new object[2];
if (value == null)
ret[0] = null;
else if (decimal.TryParse((string)value, out d))
ret[0] = d;
else
ret[0] = value;
ret[1] = Binding.DoNothing;
return ret;
}
}