我注意到WPF中有一点问题。
如果您在链(A <-> B, B <-> C, C <-> D ...)
中进行双向绑定属性,那么在引入两个或更多转换器之前一切正常。
现在,使用一个转换器,它仍然有效,但是当您在链(A <x> B, B <-> C, C <x> D ...)
中添加两个转换器时,如果属性变化得足够快,它可能会陷入无限循环。
似乎WPF在避免无限递归方面非常聪明,但是如果变化过快,它会阻碍阻止你的任何事情,并进入无限远。
我注意到这一点的原因是我正在为自己的颜色编辑器进行原型设计。我希望颜色选择是通过一个位图交叉色调和亮度,另一个滑块饱和度来完成的。为了确保滑块同步,我需要与转换器绑定(往返于颜色)。现在,我遇到了计算问题,所以我创建了一个管理转换的类,但只在需要时才这样做,并将所有内容绑定到那个。问题是当我超出控制范围时,如果用户非常快速地移过调色板,我会进行无限递归。
我追溯到一个有趣的效果。转换器(当设置为双向时)将触发向前,然后快速返回以反映任何转换损耗。但是当与另一个同样转换的转换器链接时,它们会像乒乓球一样无休止地来回跳动。
只有在转换器被足够快地触发时才会发生这种情况。所以我猜我溢出了一些计算递归堆栈的值。
是否有其他人注意到此效果,当人们对您的控件的“结果值属性”使用绑定时,如何避免此类问题?
答案 0 :(得分:1)
如果您的转换器不准确(例如进行数值计算),那么您将不得不以类似于此的方式打破链...
用于通知属性
而不是:
public double MyProperty
{
get
{
return _myProperty;
}
set
{
if (value != _myProperty)
{
_myProperty = value;
NotifyPropertyChanged("MyProperty");
}
}
}
使用:
public double MyProperty
{
get
{
return _myProperty;
}
set
{
if (Abs(value - _myProperty) / (Max(Abs(value), Abs(_myProperty)) + double.Epsilon) > MyEpsilon)
{
_myProperty = value;
NotifyPropertyChanged("MyProperty");
}
}
}
或类似的不准确比较,以便不准确不会产生无限循环。
依赖属性
使用Register(String, Type, Type, PropertyMetadata, ValidateValueCallback)
和PropertyMetadata(Object, PropertyChangedCallback, CoerceValueCallback)
定义CoerceValueCallback以防止小的更改(使用与上面相同的算法)。