绑定链错误

时间:2012-06-08 19:47:14

标签: c# wpf binding ivalueconverter

我注意到WPF中有一点问题。 如果您在链(A <-> B, B <-> C, C <-> D ...)中进行双向绑定属性,那么在引入两个或更多转换器之前一切正常。

现在,使用一个转换器,它仍然有效,但是当您在链(A <x> B, B <-> C, C <x> D ...)中添加两个转换器时,如果属性变化得足够快,它可能会陷入无限循环。

似乎WPF在避免无限递归方面非常聪明,但是如果变化过快,它会阻碍阻止你的任何事情,并进入无限远。

我注意到这一点的原因是我正在为自己的颜色编辑器进行原型设计。我希望颜色选择是通过一个位图交叉色调和亮度,另一个滑块饱和度来完成的。为了确保滑块同步,我需要与转换器绑定(往返于颜色)。现在,我遇到了计算问题,所以我创建了一个管理转换的类,但只在需要时才这样做,并将所有内容绑定到那个。问题是当我超出控制范围时,如果用户非常快速地移过调色板,我会进行无限递归。

我追溯到一个有趣的效果。转换器(当设置为双向时)将触发向前,然后快速返回以反映任何转换损耗。但是当与另一个同样转换的转换器链接时,它们会像乒乓球一样无休止地来回跳动。

只有在转换器被足够快地触发时才会发生这种情况。所以我猜我溢出了一些计算递归堆栈的值。

是否有其他人注意到此效果,当人们对您的控件的“结果值属性”使用绑定时,如何避免此类问题?

1 个答案:

答案 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以防止小的更改(使用与上面相同的算法)。