Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

背景(前回のあらすじ)

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」です。

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

…おしい!

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

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

おお!素晴らしい!

ん?カンマはいずこへ?

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は、改造前のコンバーターなら起きません。

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

完結編‼へつづく。

h084
C#やWPF周辺について書いていこうと考えています!
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした