Reputation: 4786
I just implemented my business logic validation according to Rachel Lim's blog. Everything was running great until I decided to put a trigger in my view bound to the IsValid property like this:
<ListBox ItemsSource="{Binding EdgedBoards}" SelectedItem="{Binding SelEdgedBoard, Mode=TwoWay}" DisplayMemberPath="Name">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}" BasedOn="{StaticResource {x:Type ListBoxItem}}">
<Setter Property="Focusable" Value="True" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsValid}" Value="False">
<Setter Property="Focusable" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
The problem is that when the bound item has an error (SelEdgedBoard.IsValid == false) the trigger is not notified to reevaluate and the item keeps its focusable property to true.
I've already tried to put a NotifyPropertyChanged("IsValid") before the GetValidationError() returns its value, but this way I get a stackoverflow exception:
#region IsValid Property
public bool IsValid
{
get
{
return string.IsNullOrWhiteSpace(GetValidationError());
}
}
public string GetValidationError()
{
string error = null;
if (ValidatedProperties != null)
{
foreach (string s in ValidatedProperties)
{
error = GetValidationError(s);
if (!string.IsNullOrWhiteSpace(error))
{
break;
}
}
}
NotifyPropertyChanged("IsValid");
return error;
}
#endregion
Upvotes: 0
Views: 1965
Reputation: 12315
private bool _isValid;
public bool IsValid
{
get
{
string.IsNullOrWhiteSpace(GetValidationError())
return _isValid;
}
set
{
_isValid = value;
NotifyPropertyChanged("IsValid");
}
}
public string GetValidationError()
{
string error = null;
if (ValidatedProperties != null)
{
foreach (string s in ValidatedProperties)
{
error = GetValidationError(s);
if (!string.IsNullOrWhiteSpace(error))
{
break;
}
}
}
IsValid=string.IsNullOrWhiteSpace(error);
return error;
}
I hope this will help.
Upvotes: 0
Reputation: 45155
Of course it causes a stack overflow. When you do:
NotifyPropertyChanged("IsValid")
You force the WPF infrastructure to reevaluate the value of IsValid. It does this by calling the IsValid getter, which, in turn, calls GetValidationError again!
There are several ways you can handle this. I would probably create a private member variable to hold the last value of IsValid and then compare the current value to the old value before calling NotifyPropertyChanged.
Another way might be to only call NotifyPropertyChanged("IsValid") when one of your validated properties changes (so in the setter of each of those properties) as this is what might cause a change in IsValid.
Upvotes: 3