ViewModelプロパティを更新するときに再帰を回避するにはどうすればよいですか?

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

  •  06-07-2019
  •  | 
  •  

質問

ビューには、スライダーコンボボックスがあります。

スライダーを変更するとき、コンボボックスを変更したい。

コンボボックスを変更するとき、スライダーを変更したい。

どちらか一方を更新できますが、両方を更新しようとすると、 StackOverflowエラーが発生します。1つのプロパティが無限ループでもう一方を更新し続けるためです。

更新が1か所で行われる 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プロパティを2回呼び出しても、別の変更イベントは発生しません。

もちろん、他のプロパティについても同様に行う必要があります。

他のヒント

両方のプロパティは互いに呼び出されるため、再帰です。バインディングとはまったく関係ありません。適切な方法は、互いに変更し、いずれかのプロパティが変更されたときに両方のプロパティの変更通知を起動することです:

    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