Обновление свойств и событие пинг-понга

В приложении WPF, которое использует Catel для MVVM Framework, у меня есть 3 различных свойства в модели представления

    public double? QtaDiv1 { get; set; }

    public double? Exchange{ get; set; }

    public double? QtaDiv2 { get; set; }

Я переопределил OnPropertyChanged как

protected async override void OnPropertyChanged(AdvancedPropertyChangedEventArgs e)
    {
        if (e.PropertyName == "Data")
        {
            await GetValueDate(e);
        }
        else if (e.PropertyName == "QtaDiv1" || e.PropertyName == "Exchange")
        {
            ChangeQtaDiv2(QtaDiv1, Exchange);
        }
        if (e.PropertyName == "QtaDiv2")
        {
            ChangeQtaDiv1(QtaDiv2, Exchange);
        }
        else if (e.PropertyName == "SelectedCross")
        {
            await GetValueDate(e);
            CheckForSplitVisibility();
        }

        base.OnPropertyChanged(e);
    }

И что я делаю, если значения QtaDiv1 и Exchangehave я вычисляю QtaDiv2. В противном случае, если пользователь (и Exchange) изменяет QtaDiv2, я обновляю QtaDiv1.

Это работает нормально, пока я не обновлю QtaDiv2, так как в этот момент я получил PropertyChanged на QtaDiv1, который вызывает обновление QtaDiv2 и так далее...

Как я могу разрушить это заклинание??? Я думал о настройке строкового поля, содержащего изменяющееся значение, но если я сделаю это, мне придется подавить уведомление RaisePropertyChanged (и я должен преобразовать в свойство вспомогательного поля), чтобы я не получал проверку на них

Спасибо

2 ответа

Решение

Вам просто нужно добавить простую bool переменная, чтобы указать, произошло ли изменение изнутри кода или нет:

private bool isInternalChange = false;

Если это внутреннее изменение, то вы можете игнорировать это:

if (!isInternalChange)
{
    if (e.PropertyName == "Data")
    {
        await GetValueDate(e);
    }
    else if (e.PropertyName == "QtaDiv1" || e.PropertyName == "Exchange")
    {
        isInternalChange = true;
        ChangeQtaDiv2(QtaDiv1, Exchange);
        isInternalChange = false;
    }
    if (e.PropertyName == "QtaDiv2")
    {
        isInternalChange = true;
        ChangeQtaDiv1(QtaDiv2, Exchange);
        isInternalChange = false;
    }
    else if (e.PropertyName == "SelectedCross")
    {
        await GetValueDate(e);
        CheckForSplitVisibility();
    }

    base.OnPropertyChanged(e);
}

Ответ @Sheridan правильный. Как указывает @Boris B., лучше попробовать это... наконец. Вы можете сделать это так, используя Catel:

if (!_isInternalChange)
{
    if (e.HasPropertyChanged(() => Data))
    {
        await GetValueDate(e);
    }
    else if (e.HasPropertyChanged(() => QtaDiv1) || e.HasPropertyChanged(() => Exchange))
    {
        using (StartInternalChange())
        {
            ChangeQtaDiv2(QtaDiv1, Exchange);
        }
    }
    if (e.HasPropertyChanged(() => QtaDiv2))
    {
        using (StartInternalChange())
        {   
            ChangeQtaDiv1(QtaDiv2, Exchange);
        }
    }
    else if (e.HasPropertyChanged(() => SelectedCross))
    {
        await GetValueDate(e);
        CheckForSplitVisibility();
    }

    base.OnPropertyChanged(e);
}

private IDisposable StartInternalChange()
{
    return new DisposableToken<MyClass>(this, 
        x => x._isInternalUpdate = false,
        x => x._isInternalUpdate = true);
}
Другие вопросы по тегам