绑定来验证双场 [英] Binding to double field with validation

查看:98
本文介绍了绑定来验证双场的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图绑定文本框双击与一些对象的属性 UpdateSourceTrigger =的PropertyChanged 。我们的目标是立即在编辑验证输入值是在允许的范围内(如果不显示错误)。我想落实示范级验证,即通过 IDataErrorInfo的

当我绑定到int属性所有的伟大工程,但如果财产是双然后会出现一个令人沮丧的编辑行为:在数量上的小数部分的擦除最后显著数字之后 - 小数点分隔符被自动删除(包括所有可能的分数零)。例如,自号'12 0.03擦除数字3后的文字被改为12,而不是'12 0.0。

请,帮助。

下面是示例code:

MainWindow.xaml:

 <窗​​口x:类=BindWithValidation.MainWindow
        的xmlns =htt​​p://schemas.microsoft.com/winfx/2006/xaml/$p$psentation
        的xmlns:X =htt​​p://schemas.microsoft.com/winfx/2006/xaml
        标题=主窗口HEIGHT =80WIDTH =200WindowStartupLocation =CenterOwner>  <&StackPanel的GT;
    <文本框宽度=100保证金=10文本={结合DoubleField,UpdateSourceTrigger = PropertyChanged的,ValidatesOnDataErrors = TRUE}>
      < TextBox.Style>
        <风格的TargetType =文本框>
          < Style.Triggers>
            <触发属性=Validation.HasErrorVALUE =真正的>
              < setter属性=工具提示VALUE ={绑定的RelativeSource = {自我的RelativeSource},路径=(Validation.Errors)[0] .ErrorContent}/>
            < /触发>
          < /Style.Triggers>
        < /样式和GT;
      < /TextBox.Style>
    < /文本框>
  < / StackPanel的>
< /窗GT;

MainWindow.xaml.cs:

 命名空间BindWithValidation
{
  公共部分类主窗口:窗口
  {
    私人UISimpleData _uiData =新UISimpleData();    公共主窗口()
    {
      的InitializeComponent();
      的DataContext = _uiData;
    }
  }
}

UISimpleData.cs:

 命名空间BindWithValidation
{
  公共类UISimpleData:INotifyPropertyChanged的,IDataErrorInfo的
  {
    私人双_doubleField = 12.03;    公共双DoubleField
    {
      得到
      {
        返回_doubleField;
      }
      组
      {
        如果(_doubleField ==值)
          返回;        _doubleField =价值;
        RaisePropertyChanged(DoubleField);
      }
    }    公共字符串此[字符串propertyName的]
    {
      得到
      {
        字符串的ValidationResult = NULL;
        开关(propertyName的)
        {
          案DoubleField:
          {
            如果(DoubleField 2 || DoubleField→5)
              为ValidationResult =DoubleField超出范围;
            打破;
          }          默认:
            抛出新ApplicationException的(财产来源不明被验证的UIData);
        }        返回的ValidationResult;
      }
    }    公共字符串错误{{返回无法执行; }}    公共事件PropertyChangedEventHandler的PropertyChanged;    保护无效RaisePropertyChanged(字符串属性)
    {
      如果(的PropertyChanged!= NULL)
        的PropertyChanged(这一点,新PropertyChangedEventArgs(属性));
    }
  }
}


解决方案

我知道我有点迟到了,但我发现一个(我认为),而干净地解决了这个问题。

一个巧妙的转换器,转换记得两倍的最后一个字符串,并返回如果存在的话应该做你想要的一切。

请注意,当用户改变文本框的内容,ConvertBack将存储字符串用户输入,解析字符串双,并将该值传递给视图模型。紧接着,转换被称为显示新改变的数值。在这一点上,存储的字符串不为空,将被退回。

如果该应用程序,而不是用户使双只改变转换被调用。这意味着缓存的字符串将是无效和一个标准的ToString()将呼吁加倍。

在这种方式,修改文本框的内容时,但应用程序仍然可以触发更改用户避免了奇怪的惊喜。

 公共类DoubleToPersistantStringConverter:的IValueConverter
{
    私人字符串lastConvertBackString;    公共对象转换(对象的值,类型TARGETTYPE,对象参数,System.Globalization.CultureInfo文化)
    {
        如果(!(值是双倍))返回NULL;        VAR stringValue的= lastConvertBackString? value.ToString();
        lastConvertBackString = NULL;        返回stringValue的;
    }    公共对象ConvertBack(对象的值,类型TARGETTYPE,对象参数,System.Globalization.CultureInfo文化)
    {
        如果(!(值为字符串))返回NULL;        双重效果;
        如果(double.TryParse((串)值,出结果))
        {
            lastConvertBackString =(字符串)值;
            返回结果;
        }        返回null;
    }
}

I'm trying to bind TextBox to double property of some object with UpdateSourceTrigger=PropertyChanged. The goal is to immediately during editing validate entered value to be in allowed range (and display an error if not). I want to implement validation on Model level, i.e. via IDataErrorInfo.

All works great when I bind to int property, but if property is double then a frustrating editing behavior appears: after erasing last significant digit in fractional part of number - the decimal separator is automatically erased (with all possible fractional zeroes). For example, after erasing digit '3' from number '12.03' the text is changed to '12' instead of '12.0'.

Please, help.

Here is the sample code:

MainWindow.xaml:

<Window x:Class="BindWithValidation.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="80" Width="200" WindowStartupLocation="CenterOwner">

  <StackPanel>
    <TextBox Width="100" Margin="10" Text="{Binding DoubleField, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}">
      <TextBox.Style>
        <Style TargetType="TextBox">
          <Style.Triggers>
            <Trigger Property="Validation.HasError" Value="true">
              <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}"/>
            </Trigger>
          </Style.Triggers>
        </Style>
      </TextBox.Style>
    </TextBox>
  </StackPanel>
</Window>

MainWindow.xaml.cs:

namespace BindWithValidation
{
  public partial class MainWindow : Window
  {
    private UISimpleData _uiData = new UISimpleData();

    public MainWindow()
    {
      InitializeComponent();
      DataContext = _uiData;
    }
  }
}

UISimpleData.cs:

namespace BindWithValidation
{
  public class UISimpleData : INotifyPropertyChanged, IDataErrorInfo
  {
    private double _doubleField = 12.03;

    public double DoubleField
    {
      get
      {
        return _doubleField;
      }
      set
      {
        if (_doubleField == value)
          return;

        _doubleField = value;
        RaisePropertyChanged("DoubleField");
      }
    }

    public string this[string propertyName]
    {
      get
      {
        string validationResult = null;
        switch (propertyName)
        {
          case "DoubleField":
          {
            if (DoubleField < 2 || DoubleField > 5)
              validationResult = "DoubleField is out of range";
            break;
          }

          default:
            throw new ApplicationException("Unknown Property being validated on UIData");
        }

        return validationResult;
      }
    }

    public string Error { get { return "not implemented"; } }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void RaisePropertyChanged(string property)
    {
      if ( PropertyChanged != null )
        PropertyChanged(this, new PropertyChangedEventArgs(property)); 
    }
  }
}

解决方案

I realize I'm a little late to the party but I found a (I think) rather clean solution to this problem.

A clever converter that remembers the last string converted to double and returns that if it exists should do everything you want.

Note that when the user changes the contents of the textbox, ConvertBack will store the string the user input, parse the string for a double, and pass that value to the view model. Immediately after, Convert is called to display the newly changed value. At this point, the stored string is not null and will be returned.

If the application instead of the user causes the double to change only Convert is called. This means that the cached string will be null and a standard ToString() will be called on the double.

In this way, the user avoids strange surprises when modifying the contents of the textbox but the application can still trigger a change.

public class DoubleToPersistantStringConverter : IValueConverter
{
    private string lastConvertBackString;

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (!(value is double)) return null;

        var stringValue = lastConvertBackString ?? value.ToString();
        lastConvertBackString = null;

        return stringValue;
    }

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

        double result;
        if (double.TryParse((string)value, out result))
        {
            lastConvertBackString = (string)value;
            return result;
        }

        return null;
    }
}

这篇关于绑定来验证双场的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆