Как я могу избежать рекурсии при обновлении моих свойств ViewModel?
-
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");
}
}