1

我注意到 WPF 中的一个小问题。如果你在一个链中双向绑定属性,那么在(A <-> B, B <-> C, C <-> D ...)你引入两个或更多转换器之前一切都很好。

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

似乎 WPF 在避免无限递归方面非常聪明,但如果变化来得太快,它会阻碍任何阻碍你的东西,并进入无穷大。

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

我将其追溯到一个有趣的效果。转换器(当设置为两种方式时)将向前触发,然后快速返回以反映任何转换损失。但是,当与另一个执行相同操作的转换器链接时,它们会无休止地来回弹跳,就像乒乓球一样。

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

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

4

1 回答 1

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)andPropertyMetadata(Object, PropertyChangedCallback, CoerceValueCallback)定义 CoerceValueCallback 以防止小的更改(使用与上述相同的算法)。

于 2012-06-08T20:06:38.277 回答