Значение текстового поля WPF не включает десятичную цифру 0 - PullRequest
0 голосов
/ 17 мая 2011

В событии 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
}

Ответы [ 2 ]

0 голосов
/ 18 мая 2011

Рекомендуется использовать PreviewKeyUp или PreviewTextInput, а не событие KeyUp.

В качестве альтернативы вы можете замаскировать текстовое поле, либо
1. используя MaskedTextBox , ИЛИ
2. с помощью изменив поведение текстового поля с помощью присоединенного свойства.

В случае 2 вы можете изменить функцию ValidateValue для своих требований.

0 голосов
/ 17 мая 2011

По сути, я пытался воспроизвести поведение без конвертера (поскольку я не знаю, как оно связано), и, если я хорошо выполняю ожидаемое поведение, оно работает хорошо ...

КогдаЯ ввожу 5.88, последняя цифра стирается (я получаю 5.8).Когда я ввожу 5.80, последняя цифра также стирается (я получаю 5.8).

Не могли бы вы конкретнее сказать, что вы не можете сделать?Вы пробовали без какого-либо конвертера?Или вы можете обновить код с помощью XAML с помощью конвертера?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...