Where to raise NotifyPropertyChanged?

跟風遠走 提交于 2019-12-12 01:48:13

问题


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

回答1:


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.




回答2:


        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.



来源:https://stackoverflow.com/questions/11651446/where-to-raise-notifypropertychanged

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!