Я пытаюсь найти элегантный способ проверки двух связанных значений TextBox в WPF.
Свойство Text каждого текстового поля привязано к общедоступному десятичному свойству в моем классе, который реализует привязку INotifyPropertyChanged для TwoWay.
Я хочу проверить два значения таким образом, что: BiggerValue >= SmallerValue >= 0
Мне удалось получить каждое значение для проверки независимо от этих условий с помощью IDataErrorInfo и индексатора строк.
Моя проблема заключается в следующем: пользователь намеревается уменьшить оба значения и начать с BiggerValue, так что теперь он меньше, чем SmallerValue. Проверка на BiggerValue TextBox не выполняется (хотя значение сохраняется). Затем пользователь переходит к SmallerValue и устанавливает его меньше, чем новый BiggerValue. Теперь оба значения действительны снова, но как я могу заставить текстовое поле BiggerValue автоматически отражать, что его (неизменное) значение теперь действительно?
Должен ли я искать обработчик событий, например LostFocus() в текстовых полях, или добавлять что-то вроде этого в средства настройки свойств, чтобы принудительно обновить?
biggerValueTextBox.GetBindingExpression(TextBox.TextProperty).UpdateSource();
smallerValueTextBox.GetBindingExpression(TextBox.TextProperty).UpdateSource();
Мой полный код приведен ниже. Как-то все это кажется довольно неуклюжим и сложным для этой простой проблемы. Будучи новичком WPF (это второй день), любые комментарии о моем подходе, пусть и радикальные, будут с благодарностью приняты.
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}" />
С#:
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));
}
}
ну, простой хакерский метод должен был бы также изменить свойство свойства для largeValue (это приведет к обновлению проверки для большего значения):
public decimal SmallerValue
{
get
{
return smallerValue;
}
set
{
bool fireForBigger = smallerValue > biggerValue && smallerValue < value;
smallerValue = value;
OnPropertyChanged("SmallerValue");
if (fireForBigger)
{
OnPropertyChanged("BiggerValue");
}
}
}
Но более твердое решение заключалось бы в создании пользовательских правил валидации и их настройке самостоятельно: http://msdn.microsoft.com/en-us/library/system.windows.data.binding.validationrules.aspx