如何基于彼此更改两个可观察属性,但防止死锁?
为了这个例子,我保持非常简单:
我正在数两件事,(1)物品和(2)这些物品的容器。每个容器可容纳 3 件物品。用户可以更改物品的数量和容器的数量。更改其中一个会自动更改另一个。
可以想象,这会导致完全僵局。然而当一个人改变了。我还需要更改另一个属性,并且当一个或另一个属性更改时,我需要使用新数字更新视图。
显示值:
<Entry Text="{Binding Amount}"/>
<Entry Text="{Binding Sections"/>
设定值:
private int amount;
public int Amount
{
get => amount;
set
{
SetProperty(ref amount, value);
Sections = Convert.ToInt32(Math.Round(Amount / 3));
}
}
private int sections;
public int Sections
{
get => sections;
set
{
SetProperty(ref sections, value);
Amount = Sections * 3;
}
}
如何防止死锁,例如仅在用户调用时更改属性一次?
创建两个方法来更新属性
void SetAmount(int amount)
{
this.Amount = amount;
Sections = Convert.ToInt32(Math.Round(Amount / 3));
}
void SetSections(int sections)
{
this.Sections = sections;
Amount = Sections * 3;
}
这样属性设置器就不会递归地互相调用
您可以实现一个标志,以便只有您正在设置的属性才会触发另一个属性的设置。您设置部分,它会更新部分和金额,但金额不会触发部分更新。
public class TestClass
{
private bool _updating = false;
private int _amount;
public int Amount
{
get => _amount;
set
{
_amount = value;
if (!_updating)
{
_updating = true;
Sections = Convert.ToInt32(Math.Round(Convert.ToDouble(Amount / 3)));
_updating = false;
}
}
}
private int _sections;
public int Sections
{
get => _sections;
set
{
_sections = value;
if (!_updating)
{
_updating = true;
Amount = _sections * 3;
_updating = false;
}
}
}
}
然后您可以调用设置器,而不必担心无限循环:
static void Main()
{
var tc = new TestClass();
Console.WriteLine("Set sections = 5");
tc.Sections = 5;
Console.WriteLine($"Sections: {tc.Sections}; Amount: {tc.Amount}");
Console.WriteLine("Set amount = 10");
tc.Amount = 10;
Console.WriteLine($"Sections: {tc.Sections}; Amount: {tc.Amount}");
}
产生这个结果:
设置部分 = 5
节数:5; 数量:15
设定数量=10
节数:3; 数量:10