Как я могу избежать рекурсии при обновлении моих свойств ViewModel?

StackOverflow https://stackoverflow.com/questions/1012812

  •  06-07-2019
  •  | 
  •  

Вопрос

В моем представлении есть слайдер и комбинированный список .

Когда я изменю ползунок , я хочу, чтобы поле со списком изменилось.

Когда я изменю комбинированный список , я хочу, чтобы ползунок изменился.

Я могу обновить одно или другое, но если я пытаюсь обновить оба, я получаю ошибку StackOverflow , так как одно свойство продолжает обновлять другое в бесконечном цикле.

Я пытался вставить Recalculate () , где обновление выполняется в одном месте, но все еще сталкиваюсь с проблемой рекурсии.

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

в представлении

<ComboBox 
    ItemsSource="{Binding Customers}"
    ItemTemplate="{StaticResource CustomerComboBoxTemplate}"
    Margin="20"
    HorizontalAlignment="Left"
    SelectedItem="{Binding SelectedCustomer, Mode=TwoWay}"/>


<Slider Minimum="0" 
        Maximum="{Binding HighestCustomerIndex, Mode=TwoWay}" 
        Value="{Binding SelectedCustomerIndex, Mode=TwoWay}"/>

в ViewModel:

#region ViewModelProperty: SelectedCustomer
private Customer _selectedCustomer;
public Customer SelectedCustomer
{
    get
    {
        return _selectedCustomer;
    }

    set
    {
        _selectedCustomer = value;
        OnPropertyChanged("SelectedCustomer");
        SelectedCustomerIndex = _customers.IndexOf(_selectedCustomer);
    }
}
#endregion

#region ViewModelProperty: SelectedCustomerIndex
private int _selectedCustomerIndex;
public int SelectedCustomerIndex
{
    get
    {
        return _selectedCustomerIndex;
    }

    set
    {
        _selectedCustomerIndex = value;
        OnPropertyChanged("SelectedCustomerIndex");
        SelectedCustomer = _customers[_selectedCustomerIndex];
    }
}
#endregion
Это было полезно?

Решение

попробуйте в наборе функций что-то вроде:

public int SelectedCustomerIndex
{
    get
    {
        return _selectedCustomerIndex;
    }

    set
    {
        if (value != _selectedCustomerIndex)
        {
         _selectedCustomerIndex = value;
         OnPropertyChanged("SelectedCustomerIndex");
         SelectedCustomer = _customers[_selectedCustomerIndex];
        }
    }
}

запускать события только при фактическом изменении значения. Таким образом, второй вызов свойства set с тем же значением не вызывает другого события изменения.

Конечно, вы должны сделать это и для другого свойства.

Другие советы

Оба свойства вызываются друг от друга, следовательно, рекурсия. Не имеет отношения к связыванию вообще. Правильный способ состоит в том, чтобы менять друг друга и запускать уведомление об изменении обоих свойств при изменении любого из этих свойств:

    public Customer SelectedCustomer
    {
        get
        {
            return _selectedCustomerIndex;
        }

        set
        {
            _selectedCustomer = value;
            _selectedCustomerIndex = _customers.IndexOf(value);

            OnPropertyChanged("SelectedCustomer");
            OnPropertyChanged("SelectedCustomerIndex");
        }
    }

    public int SelectedCustomerIndex
    {
        get
        {
            return _selectedCustomerIndex;
        }

        set
        {
            _selectedCustomerIndex = value;
            _selectedCustomer = _customers[_selectedCustomerIndex];

            OnPropertyChanged("SelectedCustomer");
            OnPropertyChanged("SelectedCustomerIndex");
        }
    }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top