我设置了两个相互抵消的复选框。
我认为看到的行为是一个无限循环(复选框1检查2检查1检查2 ...)
相反,在RxUI检查另一个其他复选框后,停止更改传播。
在RxUI中是否有某种循环引用的检测?
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 :(得分:2)
我认为您希望代码导致无限循环是错误的。
有两种情况。我们分开考虑一下。
1)假设最初两个属性具有相同的值(假设它是假的)。将P1更改为true将触发第一次订阅,这将尝试将P2设置为当前P1的反向(反向为真== false)。这意味着它会尝试将false设置为已经错误的东西,因此不会发生任何事情(这就是SELECT Db_name(database_id) Database_Name
,o.NAME
,indexname = i.NAME
,i.index_id
,reads = user_seeks + user_scans + user_lookups
,writes = user_updates
,rows = (SELECT Sum(p.rows)
FROM sys.partitions p
WHERE p.index_id = s.index_id
AND s.object_id = p.object_id)
,CASE
WHEN s.user_updates < 1 THEN 100
ELSE 1.00 * ( s.user_seeks + s.user_scans + s.user_lookups ) /
s.user_updates
END AS reads_per_write
,'DROP INDEX ' + Quotename(i.NAME) + ' ON '
+ Quotename(c.NAME) + '.'
+ Quotename(Object_name(s.object_id)) AS 'drop statement'
FROM sys.dm_db_index_usage_stats s
INNER JOIN sys.indexes i
ON i.index_id = s.index_id
AND s.object_id = i.object_id
INNER JOIN sys.objects o
ON s.object_id = o.object_id
INNER JOIN sys.schemas c
ON o.schema_id = c.schema_id
WHERE Objectproperty(s.object_id, 'IsUserTable') = 1
AND s.database_id = Db_id()
AND i.type_desc = 'nonclustered'
AND i.is_primary_key = 0
AND i.is_unique_constraint = 0
AND (SELECT Sum(p.rows)
FROM sys.partitions p
WHERE p.index_id = s.index_id
AND s.object_id = p.object_id) > 10000
ORDER BY reads_per_write ASC
给你的东西 - 在设置属性之前,它会检查它是否已经改变)。
2)现在P1最初为真,P2为假。将P1更改为false会触发第一个订阅,即将P2设置为(!P1),在这种情况下为true。因此,P2从false变为true。这会触发第二次订阅,尝试将P1设置为(!P2),现在为false。但P1已经是假的,因此属性不会改变(因此NotifyPropertyChanged不会触发)。
因此,通过不盲目设置属性来破坏循环,但首先检查它是否发生了变化(以避免不必要的NotifyPropertyChanged事件)。
当您意识到[Reactive]
转化为:
[Reactive]
注意名称 - RaiseAndSet IfChanged 。
现在,如果你想看到一个无限循环......只需将你的代码改为:
private bool _prop2;
public bool Prop2
{
get { return _prop2; }
set { this.RaiseAndSetIfChanged(ref _prop2, value); }
}
这给了我 public VM01()
{
this.WhenAnyValue(x => x.Prop1)
.Subscribe(x => Prop2 = !Prop2);
this.WhenAnyValue(x => x.Prop2)
.Subscribe(x => Prop1 = !Prop1);
}
。