WPFでTextBoxにdoubleをBindingすると
- 文字の末尾に小数点を入力できない
1.002
の2を消すと1.00
ではなく1
になる
などの動作になります。
これはBindingしている値をTextBoxにも即反映させるという動作になっているからです。
1.002
の末尾の2を消した際の動作は下記のようになります。
Text
が1.00
に更新- Binding Sourceのdoubleが
(double)1
に更新 Text
が1
に更新
雑な解決
起動時に
App.xaml.cs
System.Windows.FrameworkCompatibilityPreferences.KeepTextBoxDisplaySynchronizedWithTextProperty=false;
と設定すれば解決です。
Bindingしている値をTextBoxにも即反映させないようにします。
.NET Framework 4.5以前はこれがデフォルトです。
解決
Text
プロパティを更新する前に別のプロパティでチェックを行うことで期待する動作を実現します。
Text
は設定せずにDoubleTextのみを使います。
<myControl:DoubleTextBoxDoubleText="{Binding Double1, UpdateSourceTrigger=PropertyChanged}"/>
usingSystem;usingSystem.Windows;usingSystem.Windows.Controls;usingSystem.Windows.Data;publicclassDoubleTextBox:TextBox{publicstringDoubleText{get=>(string)GetValue(DoubleTextProperty);set=>SetValue(DoubleTextProperty,value);}publicstaticreadonlyDependencyPropertyDoubleTextProperty=DependencyProperty.Register(nameof(DoubleText),typeof(string),typeof(DoubleTextBox),newFrameworkPropertyMetadata(string.Empty,FrameworkPropertyMetadataOptions.BindsTwoWayByDefault|FrameworkPropertyMetadataOptions.Journal,newPropertyChangedCallback(OnDoubleTextChanged),null,true,UpdateSourceTrigger.LostFocus));privatestaticvoidOnDoubleTextChanged(DependencyObjectd,DependencyPropertyChangedEventArgse){if(disTextBoxtextBox){varcurrentText=textBox.Text;varnewText=(string)e.NewValue;if(currentText==newText)return;if(double.TryParse(currentText,outvarcurrentDouble)&&double.TryParse(newText,outvarnewDouble)&¤tDouble==newDouble)return;textBox.Text=newText;}}protectedoverridevoidOnTextChanged(TextChangedEventArgse){base.OnTextChanged(e);this.DoubleText=this.Text;}}
動作の解説
これによって、1.002
の末尾の2を消した際の動作は下記のようになります。
Text
が1.00
に更新DoubleText
が1.00
に更新- Binding Sourceのdoubleが
(double)1
に更新 DoubleText
が1
に更新1
と1.00
はともにdouble値として等しいのでText
は更新されない
Textが更新された場合の動作
キーの入力などでText
が更新されたときはその値がそのままDoubleText
に反映されます。
Binding Sourceへも同様に反映されます。
DoubleText(あるいはBinding Source)が更新された場合の動作
基本的にはText
に反映されます。
ただし、DoubleText
とText
をそれぞれdoubleに変換して同じ値になる場合はText
を更新しません。