Reputation: 2588
I have a problem with validations between multiple fields. For example, I have a ViewModel named RangeDateViewModel
that contains 2 instances of a class named DateViewModel
- they represent a start date and an end date respectively.
So my binding looks like this:
<TextBox Text="{Binding StartDate.Date, ValidateOnDataError=True}">
<TextBox Text="{Binding EndDate.Date, ValidateOnDataError=True}">
My RangeDateViewModel
class implements the IDataErrorInfo
interface.
In my plan, the RangeDateViewModel
would validate that the start date is before the end date, by applying the validation logic in the IDataErrorInfo["propertyName"]
function like this:
public string this[string columnName]
{
get
{
return ValidationError();
}
}
The problem is that this is never being called, and instead the IDataErrorInfo
properties that reside in each of the DateViewModel
classes are being called instead.
I guess this is because the bound property is not in the same level of RangeDateViewModel
, but instead inside the child DateViewModel
.
I think my need is quite basic and there must be an easy solution for this problem.
I tried using ValidationRules instead of IDataErrorInfo
but then I'd problems letting the ViewModel know of the current validation status from the ValidationRules.
Upvotes: 5
Views: 1511
Reputation: 174467
Try using the following approach:
Create a DataTemplate
for DateViewModel
:
<DataTemplate DataType="{x:Type ViewModels:DateViewModel}">
<TextBox Text="{Binding Date}">
</DataTemplate>
Bind the instances of this ViewModel to a ContentControl and set ValidateOnDataError
to true
on that binding:
<ContentControl Content="{Binding StartDate, ValidateOnDataError=True}" />
<ContentControl Content="{Binding EndDate, ValidateOnDataError=True}" />
In RangeDateViewModel
subscribe to the PropertyChanged
event of StartDate
and EndDate
and when raised, raise a PropertyChanged
event with StartDate
/ EndDate
:
StartDate.PropertyChanged += (s, e) => InvokePropertyChanged("StartDate");
EndDate.PropertyChanged += (s, e) => InvokePropertyChanged("EndDate");
Upvotes: 1
Reputation: 4632
I had the problem that public string this[string columnName]
was simply not called just the other week.
The solution was simple. The binding WPF binding engine could not follow the nesting of my ViewModels.
I had assumed that I needed to implement the property in the ViewModel that is the current DataContext, but instead it needs to be implemented in the ViewModel that is bound to the control.
Example:
<TextBox Text="{Binding Path=ProductViewModel.DescriptionViewModel.ProductName,
Mode=TwoWay,
ValidatesOnDataErrors=True,
NotifyOnValidationError=True}" />
Here DescriptionViewModel
is the class that contains the bound property. IDataErrorInfo
needs to be implemented in that class (not in ProductViewModel
or another class up the hierarchy that may contain it) then everything will work fine.
Upvotes: 1