0

我刚刚根据 Rachel Lim 的博客实现了我的业务逻辑验证。一切都运行良好,直到我决定在绑定到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)时,触发器不会被通知重新评估,并且项目将其可聚焦属性保持为真。

我已经尝试在 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
4

2 回答 2

3

当然,它会导致堆栈溢出。当你这样做时:

NotifyPropertyChanged("IsValid")

您强制 WPF 基础结构重新评估 IsValid 的值。它通过调用 IsValid getter 来做到这一点,而后者又再次调用 GetValidationError!

有几种方法可以处理这个问题。我可能会创建一个私有成员变量来保存 IsValid 的最后一个值,然后在调用 NotifyPropertyChanged 之前将当前值与旧值进行比较。

另一种方法可能是仅在您的已验证属性之一发生更改时调用 NotifyPropertyChanged("IsValid")(因此在每个属性的设置器中),因为这可能会导致 IsValid 发生更改。

于 2012-07-25T14:06:53.303 回答
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;
    }

我希望这将有所帮助。

于 2012-07-25T14:07:49.263 回答