В событии KeyUp текстового поля WPF значение textBox.Text является правильным, если пользователь не вводит 0. Например, если пользователь вводит 5.88, значение textBox.Text равно «5.88».Если пользователь вводит 5,80, значение textBox.Text равно «5,8» (0 удаляется).Мы разрешаем пользователю вводить только одну десятичную цифру, поэтому, если они вводят 5.80, мы хотим обрезать 0. Проблема в том, что мы не можем, потому что код, который выполняет обрезку, видит только «5.8».Когда операция завершена, в текстовом поле по-прежнему появляется «5,80», чтобы пользователь мог ее увидеть.
Есть идеи, почему это произойдет?
Примечание. К текстовому полю применяется преобразователь,но событие KeyUp устанавливает значение textBox.Text.Таким образом, если преобразователь выдает 5.8, значение textBox.Text устанавливается на «5.8».
Редактировать: Вот часть кода:
<Window.Resources>
<converters:StringToBooleanConverter x:Key="stringToBooleanConverter" />
<converters:SecondsToMinutesConverter x:Key="secondsToMinutesConverter" />
</Window.Resources>
<TextBox Text="{Binding ApplyTimeInSeconds, Converter={StaticResource secondsToMinutesConverter},
TargetNullValue={x:Static sys:String.Empty}, UpdateSourceTrigger=PropertyChanged,
NotifyOnValidationError=True, ValidatesOnExceptions=True}"
vab:Validate.BindingForProperty="Text"
Name="ApplyTimeTextBox"
KeyUp="ApplyTimeTextBox_KeyUp"
Width="75" VerticalAlignment="Center" Style="{StaticResource textBoxInError}"
IsEnabled="{Binding ElementName=applyTimeCheckbox, Path=IsChecked}"/>
private void ApplyTimeTextBox_KeyUp(object sender, KeyEventArgs e)
{
ViewUtility.RemoveExtraDecimalDigits(sender as TextBox, 1);
}
// We don't want to allow more than one decimal position. So, if the user types 4.38, remove the 8. Or change 4.389 to 4.3.
internal static void RemoveExtraDecimalDigits(TextBox textBox, int numberOfDecimalDigitsAllowed)
{
if (!textBox.Text.Contains(".")) { return; }
string originalText = textBox.Text;
textBox.Text = GetValueWithCorrectPrecision(textBox.Text, numberOfDecimalDigitsAllowed);
// If the text changed, move the cursor to the end. If there was no change to make, or maybe the user hit the
// HOME key, no reason to move the cursor.
if (textBox.Text != originalText)
{
MoveCursorToEnd(textBox);
}
}
private static string GetValueWithCorrectPrecision(string textValue, int numberOfDecimalDigitsAllowed)
{
int indexOfDecimalPoint = textValue.IndexOf('.');
string[] numberSection = textValue.Split('.');
if (numberSection[1].Length > numberOfDecimalDigitsAllowed)
{
// Keep the decimal point and the desired number of decimal digits (precision)
return textValue.Remove(indexOfDecimalPoint + numberOfDecimalDigitsAllowed + 1);
}
return textValue;
}
private static void MoveCursorToEnd(TextBox textBox)
{
textBox.Select(textBox.Text.Length, 0); // Keep cursor at end of text box
}
А вот преобразователь:
public class SecondsToMinutesConverter : IValueConverter
{
#region IValueConverter Members
/// <summary>
/// Converts a value from the source (domain object/view model) to the target (WPF control).
/// </summary>
/// <param name="value">The value produced by the binding source.</param>
/// <param name="targetType">The type of the binding target property.</param>
/// <param name="parameter">The converter parameter to use.</param>
/// <param name="culture">The culture to use in the converter.</param>
/// <returns>
/// A converted value. If the method returns null, the valid null value is used.
/// </returns>
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if(value == null) { return null; }
decimal bindingSourceValueAsDecimal = System.Convert.ToDecimal(value, CultureInfo.CurrentCulture);
return Decimal.Round(bindingSourceValueAsDecimal / 60, 2);
}
/// <summary>
/// Converts a value from the target (WPF control) to the source (domain object/view model).
/// </summary>
/// <param name="value">The value that is produced by the binding target.</param>
/// <param name="targetType">The type to convert to.</param>
/// <param name="parameter">The converter parameter to use.</param>
/// <param name="culture">The culture to use in the converter.</param>
/// <returns>
/// A converted value. If the method returns null, the valid null value is used.
/// </returns>
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if(value == null) { return null; }
decimal bindingTargetValueAsDecimal;
if(Decimal.TryParse(value.ToString(), out bindingTargetValueAsDecimal) == false) { return DependencyProperty.UnsetValue; }
return Math.Round(bindingTargetValueAsDecimal * 60, 2);
}
#endregion
}