我刚刚根据Rachel Lim的blog实现了我的业务逻辑验证。 一切都运行良好,直到我决定在我的视图中触发一个绑定到 IsValid 属性的触发器,如下所示:
<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>
问题是当绑定项有错误(SelEdgedBoard.IsValid == false)时,不会通知触发器重新评估,并且该项将其focusable属性保持为true。
我已经尝试在GetValidationError()返回其值之前放置NotifyPropertyChanged(“IsValid”),但这样我得到了一个stackoverflow异常:
#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
答案 0 :(得分:3)
当然会导致堆栈溢出。当你这样做时:
NotifyPropertyChanged("IsValid")
您强制WPF基础结构重新评估IsValid的值。它通过调用IsValid getter来执行此操作,而getValid getter又调用了GetValidationError!
有几种方法可以解决这个问题。我可能会创建一个私有成员变量来保存IsValid的最后一个值,然后在调用NotifyPropertyChanged之前将当前值与旧值进行比较。
另一种方法可能是只在您的一个经过验证的属性发生更改时调用NotifyPropertyChanged(“IsValid”)(因此在每个属性的setter中),因为可能导致更改的IsValid。
答案 1 :(得分:0)
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;
}
我希望这会有所帮助。