2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

doubleとバインドしているTextBoxに小数点が入力できない!【解決編⁉】

Last updated at Posted at 2018-09-24

背景(前回のあらすじ)

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

  • C# + XAML
  • TextBoxが数値型のプロパティとバインドしている
  • リアルタイムに入力値でバインドしているプロパティを更新する
XAML
<TextBox Text="{Binding Path=Number,
                        Mode=TwoWay,
                        UpdateSourceTrigger=PropertyChanged}" />

このように記述した場合、バインドしているNumberint型だと問題ありません。しかし、double型だった場合、数字列の末尾に小数点が入力できないんです。

解決方法わかりません!どなたか、ご教授を!というところで終わっていました。

コメントをいただきました!

さっそく、albireoさんにコメントでご教授いただきました!ありがとうございます!

StackOverflowに「書き戻すときに元の文字列を返すようなコンバータを実装すればいい」ってのがありました。

と紹介していただいたのが、「[Binding to double field with validation][stackoverflow]」です。
[stackoverflow]:https://stackoverflow.com/questions/11223236/binding-to-double-field-with-validation "stackoverflow"

デフォルトの動作で満足できないなら、自分で処理を書きなさい、ってことですね。(そりゃそうだ)

…おしい!

[リンク先][stackoverflow]に書いてある通りのクラスを作り、コンバーターを付けてみました。

末尾の小数点が入力できます!
前回は書いていませんでしたが、できなかった小数点以下の末尾のゼロの入力もできます!

おお!素晴らしい!

ん?カンマはいずこへ?

StringFormatが効いていない!

前回は本題と関係ないと思っていましたので、紹介しているコードに書かなかったのですが、Bindingマークアップ拡張にStringFormatを付けています。

XAML
<TextBox Text="{Binding Path=Number,
                        Mode=TwoWay,
                        UpdateSourceTrigger=PropertyChanged,
                        StringFormat='#,0.#####',
                        Converter={StaticResource converter}}" />

整数部に3桁ごとのカンマを入れて表示したいんです!

コンバーターが文字列を戻しますので、StringFormatに指定した数値用の書式指定が使われず、したがってカンマが表示されません!

コンバーター改造!

コンバーターをちょっと改造し、下記のようにしてみました。

  • 値が変わらなかったときは、入力文字列(string型)を戻す
  • 値が変わったときは、StringFormatを使うように値(double型)を戻す
コンバーター・クラス
//doubleと文字列のコンバーター
public class DoubleToStringConverter : System.Windows.Data.IValueConverter
{
  private string convertBackString; //入力文字列
  private double? prevValue; //前回表示した値

  //doubleから文字列への変換(表示時に使われる)
  public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
  {
    try
    {
      if (!(value is double)) return null;

      double newValue = (double)value;
      try
      {
        if (!string.IsNullOrEmpty(convertBackString)
          && prevValue.HasValue && (prevValue == newValue))
        {
          //入力文字列があり、前回表示した値と同じ値を表示するなら、入力文字列をそのまま戻す
          return convertBackString;
        }
        else
        {
          //そうでなければ、値をdouble型で戻す
          //→StringFormatを使ってフォーマットされる
          return newValue;
        }
      }
      finally
      {
        prevValue = newValue;
      }
    }
    finally
    {
      convertBackString = null;
    }
  }

  //文字列からdoubleへの変換(入力時に使われる)
  public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
  {
    //入力文字列を保存する
    convertBackString = value as string;

    if (!string.IsNullOrEmpty(convertBackString)
      && double.TryParse(convertBackString, out double newValue))
    {
      //入力文字列をパーズして戻す
      return newValue;
    }
    else
    {
      return null;
    }
  }
}

完全に解決したわけではない…

結果は、まぁまぁいいかなって感じですね。末尾の小数点やゼロが入力できるようになりましたが、まだおかしな動作が残っています。

  1. 整数部の3桁ごとではないところへカンマが入力できてしまう
  2. 「123.4」となっていた場合に4を削除すると、「123」になる(「123.」になって欲しい)
  3. 「123.004」となっていた場合に4を削除すると、「123」になる(「123.00」になって欲しい)

1は、改造前のコンバーターでも起きます。コンバーターを付ける前には起きませんでした。2と3は、改造前のコンバーターなら起きません。

というわけで、スッキリ解決!にはなっていません。引き続き、解決法のご教授をお待ちしております!

完結編‼へつづく。

2
2
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?