WPFで2つの関連するTextBox値を検証するための洗練された方法を見つけようとしています。
各テキストボックスのTextプロパティは、TwoWayバインディングのINotifyPropertyChangedを実装するクラスのパブリックdecimalプロパティにバインドされます。
BiggerValue> = SmallerValue>=0のように2つの値を検証したい
IDataErrorInfoと文字列インデクサーを使用して、これらの条件に対して個別に検証する各値を取得することに成功しました。
私の問題は次のとおりです。ユーザーは両方の値を減らすことを意図しており、BiggerValueで開始するため、現在はSmallerValueよりも小さくなっています。BiggerValue TextBoxの検証は失敗します(値は保存されますが)。次に、ユーザーはSmallerValueに移動し、新しいBiggerValueよりも小さく設定します。これで両方の値が再び有効になりますが、BiggerValueテキストボックスにその(変更されていない)値が有効になったことを自動的に反映させるにはどうすればよいですか?
テキストボックスでLostFocus()のようなイベントハンドラーを確認する必要がありますか、それともプロパティセッターにこのようなものを追加して強制的に更新する必要がありますか?
biggerValueTextBox.GetBindingExpression(TextBox.TextProperty).UpdateSource();
smallerValueTextBox.GetBindingExpression(TextBox.TextProperty).UpdateSource();
私の完全なコードは以下の通りです。どういうわけか、この単純な問題では、すべてがかなり不格好で複雑すぎるように感じます。WPFの初心者(これは2日目です)として、私のアプローチについてのコメントは、どんなに過激であっても、ありがたいことに受け取られます。
XAML:
<TextBox x:Name="biggerValueTextBox"
Text="{Binding Path=BiggerValue,
Mode=TwoWay,
ValidatesOnDataErrors=True,
ValidatesOnExceptions=True}" />
<TextBox x:Name="smallerValueTextBox"
Text="{Binding Path=SmallerValue,
Mode=TwoWay,
ValidatesOnDataErrors=True,
ValidatesOnExceptions=True}" />
C#:
public partial class MyClass : UserControl,
INotifyPropertyChanged, IDataErrorInfo
{
// properties
private decimal biggerValue = 100;
public decimal BiggerValue
{
get
{
return biggerValue;
}
set
{
biggerValue = value;
OnPropertyChanged("BiggerValue");
}
}
private decimal smallerValue = 80;
public decimal SmallerValue
{
get
{
return smallerValue;
}
set
{
smallerValue = value;
OnPropertyChanged("SmallerValue");
}
}
// error handling
public string this[string propertyName]
{
get
{
if (propertyName == "BiggerValue")
{
if (BiggerValue < SmallerValue)
return "BiggerValue is less than SmallerValue.";
if (BiggerValue < 0)
return "BiggerValue is less than zero.";
}
if (propertyName == "SmallerValue")
{
if (BiggerValue < SmallerValue)
return "BiggerValue is less than SmallerValue.";
if (SmallerValue < 0)
return "SmallerValue is less than zero.";
}
return null;
}
}
// WPF doesn't use this property.
public string Error { get { return null; } }
// event handler for data binding
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}