簡體   English   中英

WPF文本框驗證刪除其他數字之前的0

[英]WPF TextBox validation removes 0s before other digits

我正在為綁定到TextBox的類型的屬性實現驗證規則。 問題是,當我在十進制數字中輸入0時,如果結果數字被規則接受,則WPF會刪除最后一個0,因為它認為這是數學上的偽數。 這樣可以防止我在其后輸入非0的數字。

例如,我無法輸入5.101,因為當我達到5.10時,WPF會擦除0,然后回到5.1。

我可以通過在捕獲5.10時返回失敗的ValidationResult來解決此問題,因為在這種情況下WPF不會刪除0。但這被樣式(紅色邊框)視為失敗,並且會使用戶感到困惑。

有更好的解決方法嗎?

驗證是在從ValidationRule繼承的類中進行的,Validate方法是這個。

    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
        double dValue = 0.0;
        string sValue;
        string definition = "Enter number in [ " + Min + "; " + Max + "]";

        // Catch non-double, empty, minus sign
        try
        {
            sValue = (string)value;
            if (sValue == "-")
                return new ValidationResult(false, definition);
            else if (sValue.Length > 0)
                dValue = double.Parse(sValue);
            else // Empty entry
                return new ValidationResult(false, definition);
        }
        catch (Exception ex)
        {
            return new ValidationResult(false, "Invalid entry: " + ex.Message);
        }

        // Forbid finishing with dot but return false to allow keyboard input
        if (sValue.EndsWith("."))
            return new ValidationResult(false, "Cannot end with '.'");

        // Check range
        if (dValue < Min || dValue > Max)
            return new ValidationResult(false, definition);
        else
        {
            // Workaround to allow input of 0
            if (sValue.Contains(".") && sValue.EndsWith("0"))
                return new ValidationResult(false, "Accepted");
            else
                return new ValidationResult(true, null);
        }
    }

問題似乎與對象的反饋有關。 當我從TwoWay更改為其他東西時,驗證不再阻止輸入0。 不幸的是,我確實需要TextBox在第一次綁定對象時顯示對象的內容。 但是在那之后,我只需要OneWayToSource就可以了,因為我可以重置DataContext進行更新。 當我在OneWayToSource中將對象附加到DataContext時,是否有一種方法可以用屬性值填充TextBox(不是通過顯式設置其Text)?

我希望我更好地了解WPF,以確保是否有比這更好的解決方案。 但請注意,您可以提供自己的IValueConverter來處理轉換,並且這樣做可以避免尾隨零的剝離。 例如,此轉換器僅將綁定屬性轉換為控件一次,而忽略所有后續更新事件:

class DoubleToStringConverter : IValueConverter
{
    private bool _convert = true;

    public object Convert(object value,
        Type targetType, object parameter, CultureInfo culture)
    {
        return _convert ? value.ToString() : Binding.DoNothing;
    }

    public object ConvertBack(object value,
        Type targetType, object parameter, CultureInfo culture)
    {
        string text = value as string;
        double doubleValue;

        if (text != null &&
            targetType == typeof(double) &&
            double.TryParse((string)value, out doubleValue))
        {
            _convert = false;
            return doubleValue;
        }

        return Binding.DoNothing;
    }
}

這使您可以在程序首次初始化控件時對其進行更新,但之后它將作為單向綁定,僅在更改時更新源。

坦白說,對我來說似乎有點偷偷摸摸。 但這確實有效。 :)

我在驗證時也遇到了同樣的問題,Peter的回答對我很有幫助。 但是它禁用了源(模型)的同步,這在很多情況下是不可接受的。 我走得更遠,升級了一點。 確保轉換器是標記擴展或使用選項x:Shared="False" ,在這種情況下,所有綁定都將使用其自己的轉換器實例。

public class OptimizedDoubleToStringConverter : ConverterBase
{
   private double _prevValue;

   public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
   {
      if (!(value is double) && !(value is float))
         return null;

      return XMath.Eq(_prevValue, System.Convert.ToDouble(value))
            ? Binding.DoNothing
            : value.ToString();
   }

   public override object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
   {
      if (!(value is string))
         return null;

      double doubleValue = double.Parse(value.ToString());

      if (!XMath.Eq(_prevValue, doubleValue))
         _prevValue = doubleValue;

      return doubleValue;
   }
}

ConverterBase - XMath.Eq為“轉換器作為標記擴展名”的基類-僅將浮點數與epsilon進行比較。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM