2016-12-05 5 views
1

Ich habe zwei Kontrollkästchen eingerichtet, die sich gegenseitig negieren.Erkennung von Zirkelreferenzen in RxUI

Das Verhalten, das ich sehe, dachte war eine infintite Schleife (Checkbox 1 prüft 2 Check 1 prüft, 2, ...)

Statt die Ausbreitung der Änderung nach den anderen anderen Checkbox angehalten wird, wird durch RxUI geprüft.

Gibt es eine Art von gefundenen zirkulären Referenzen in RxUI eingebaut?

using ReactiveUI; 
using ReactiveUI.Fody.Helpers; 
using System; 

namespace rxnested 
{ 
    public class VM01 : ReactiveObject 
    { 
     [Reactive] 
     public bool Prop1 { get; set; } 

     [Reactive] 
     public bool Prop2 { get; set; } 

     public VM01() 
     { 
      this.WhenAnyValue(x => x.Prop1) 
       .Subscribe(x => Prop2 = !x); 


      this.WhenAnyValue(x => x.Prop2) 
       .Subscribe(x => Prop1 = !x); 
     } 
    } 
} 

<Window x:Class="rxnested.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:local="clr-namespace:rxnested" 
     mc:Ignorable="d" 
     Title="MainWindow" 
     Height="350" 
     Width="525"> 
    <Window.DataContext> 
     <local:VM01></local:VM01> 
    </Window.DataContext> 
    <StackPanel> 
     <CheckBox IsChecked="{Binding Prop1}"></CheckBox> 
     <CheckBox IsChecked="{Binding Prop2}"></CheckBox> 
    </StackPanel> 
</Window> 
+0

Ich hoffe nicht und bezweifle es. IMO würde es den Rahmen verlangsamen. Es ist der Job des Programmierers, in diesem Fall keine Endlosschleifen unterschiedlicher Art zu erzeugen. – kenny

Antwort

2

Ich denke, dass Ihre Erwartung, dass Ihr Code in Endlosschleife führen sollte, falsch ist.

Es gibt 2 Szenarien. Betrachten wir sie getrennt.

1) Nehmen wir an, dass zunächst beide Eigenschaften den gleichen Wert haben (sagen wir es ist falsch). Wenn Sie P1 auf true setzen, wird die erste Subskription ausgelöst, die versucht, P2 in die Umkehrung des aktuellen Werts von P1 zu setzen (Umkehr von wahr == false). Das bedeutet, dass es versucht, false auf etwas zu setzen, das bereits falsch war, und somit wird nichts passieren (das gibt [Reactive] Ihnen - bevor es die Eigenschaft setzt, überprüft es, ob es sich geändert hat).

2) Jetzt ist P1 zunächst wahr und P2 ist falsch. Wenn P1 auf false geändert wird, wird die erste Subskription ausgelöst, die P2 in (! P1) setzt, was in diesem Fall wahr ist. P2 ändert sich also von falsch zu wahr. Das löst die zweite Subskription aus, die versucht, P1 in (! P2) zu setzen, was jetzt falsch ist. Aber P1 ist bereits falsch, daher ändert sich die Eigenschaft nicht (und daher wird NotifyPropertyChanged nicht ausgelöst).

So wird der Zyklus unterbrochen, indem die Eigenschaft nicht blind eingestellt wird, sondern zuerst überprüft wird, ob sie sich überhaupt geändert hat (um unnötige NotifyPropertyChanged-Ereignisse zu vermeiden).

Dies ist noch deutlicher, wenn man bedenkt, dass [Reactive] übersetzt in:

private bool _prop2; 
    public bool Prop2 
    { 
     get { return _prop2; } 
     set { this.RaiseAndSetIfChanged(ref _prop2, value); } 
    } 

Notieren Sie den Namen - RaiseAndSet IfChanged.

Nun, wenn Sie wollen eine Endlosschleife sehen .. einfach Ihren Code in das ändern:

public VM01() 
    { 
     this.WhenAnyValue(x => x.Prop1) 
      .Subscribe(x => Prop2 = !Prop2); 


     this.WhenAnyValue(x => x.Prop2) 
      .Subscribe(x => Prop1 = !Prop1); 
    } 

Das bin ich StackOverflowException gibt.