C#
.NET
WPF
Xaml
MVVM

doubleとバインドしているTextBoxに小数点が入力できない!


背景


  • C# + XAML


  • TextBoxが数値型(intdouble)とバインドしている

  • リアルタイムに入力値でバインドしているプロパティを更新する

<TextBox Text="{Binding Path=Number, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />

TextBox.Textプロパティを、数値型のNumberとバインドしています。

Mode=TwoWayとしていますので、TextBoxに入力するとその値をバインドしているNumberへ書き込みます。(これはTextBoxのデフォルトの動作ですから、記述しなくても構いませんね)

また、UpdateSourceTrigger=PropertyChangedとしていますので、TextBoxのデフォルトの動作であるフォーカスが外れたときではなく、値を入力した瞬間にNumberへ書き込みます。


int(long)だとバッチリ!

バインドしているNumberが、intlongなど整数型だと、何の問題もなく動作します!

ちなみに、数字以外の文字列を入れた場合は、枠が赤くなり、入力に誤りがあることも自動的に表示してくれます!

入力に誤りがあれば、バインドしているNumberも更新されません。

キャプチャ.PNG

なんと便利!


double(float)だと…

ところが、バインドしているNumberが、doublefloatなど小数点以下を含む数値型になると、問題が生じます!

小数点が入力できないんです!

「123.45」と左の1から順に入力していくと、小数点が入力されず「12345」になってしまいます!

小数点が全く入力できないかというと、そうでもなくて、「12345」と入力した後、「3」と「4」の間にカーソルを置き、「.」を入力すると、正しく「123.45」になります。

つまり、数字列の最後(末尾)へ小数点が入力できないんです!


どうなってるの?(推測)

System.Windows.Data Error: 7 : ConvertBack cannot convert value '123a' (type 'String'). BindingExpression:Path=Model.Number1; DataItem='SimpleCalcViewModel' (HashCode=20876819); target element is 'TextBox' (Name=''); target property is 'Text' (type 'String') FormatException:'System.FormatException: 入力文字列の形式が正しくありません。

場所 System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal)
場所 System.Number.ParseInt64(String value, NumberStyles options, NumberFormatInfo numfmt)
場所 System.String.System.IConvertible.ToInt64(IFormatProvider provider)
場所 System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider)
場所 MS.Internal.Data.SystemConvertConverter.ConvertBack(Object o, Type type, Object parameter, CultureInfo culture)
場所 System.Windows.Data.BindingExpression.ConvertBackHelper(IValueConverter converter, Object value, Type sourceType, Object parameter, CultureInfo culture)'

数値以外を入力したときに、Visual Studioの出力ウィンドウに出る例外のバックトレースから、次のような機序になっているようです。



  1. TextBoxに数字(文字)を入力する

  2. 入力された文字列全体を、Number.ParseInt64メソッドやNumber.ParseDoubleメソッドを使って、数値に変換する

  3. 変換に成功したら、その数値をTextBoxに表示する

  4. バインドしているプロパティに書き込む

ここで問題になるのが、「変換に成功したら、その数値をTextBoxに表示する」ところです。

末尾に小数点を入力すると、たとえば「123.」という文字列になります。

これをNumber.ParseDoubleメソッドが変換すると、123という数値になります。

123という数値は、表示すると「123」になり、小数点はなくなってしまいます!


どうすればいいの?(HELP!)

では、どうすればいいのかですが、すみません!まだ、わかっていません!

どなたか、ご教授いただければ幸いです!

UpdateSourceTrigger=PropertyChangedを取ればいいんですが、リアルタイムに更新されなくなっちゃいますからねぇ。リアルタイムに更新し、かつ、末尾に小数点を入力したいんですけど…。

解決編⁉完結編‼へつづく。