C#
.NET
WPF
Xaml
MVVM

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


背景(前回のあらすじ)

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

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

完結編‼へつづく。