边界变化时滑块值的正确比率

时间:2017-01-02 00:19:30

标签: c# wpf slider

我正在创建滑块,以便在最大值或最小值更改时保持当前值的比率。

这是显示我如何修正滑块上的值比例的图片。

enter image description here

(扩展第二个滑块以更好地解释解决方案。显然,应用程序视图中滑块的大小是固定的,只有内部更改值。)

这就是你看到的结果。

enter image description here

用于修正比率的公式I非常简单。这是Maximum值更改时使用的公式:

NewValue = OldValue * ((newMaximum - Minimum) / (oldMaximum - Minimum));

如果Minimum值已更改:

NewValue = OldValue * ((Maximum - newMinimum) / (Maximum - oldMinimum));

(有一些事情需要考虑,例如防止除零。但这里的主题是偏离主题。)

现在看看问题何时出现。假设newMaximum小于滑块的值。 遗憾的是滑块内部行为想要通过执行value = newMaximum来纠正该值,因此这与我的计算冲突。

下图通过反向显示问题。第二个滑块是我想要的,但我得到了第三个滑块。

enter image description here

这是我尝试过的。 (代码简化)

protected override void OnMaximumChanged(double oldMaximum, double newMaximum)
{
    if ((oldMaximum - Minimum) <= 0) oldMaximum = Minimum + 1; // prevent 0-division

    Value *= (newMaximum - Minimum) / (oldMaximum - Minimum);

    base.OnMaximumChanged(oldMaximum, newMaximum);
}

protected override void OnValueChanged(double oldValue, double newValue)
{
    //base.OnValueChanged(oldValue, newValue);
}

即使我覆盖了OnValueChanged,但滑块会在newMaximum小于value时通过执行value = newMaximum来纠正值,如图所示。 我该如何解决?

警告:以下代码可能会让您头疼!我试着解释这个问题,希望你理解。如果您想了解更多信息,请参阅我目前拥有的完整OnMaximumChanged代码。

private bool _selfChanging;

protected override void OnMaximumChanged(double oldMaximum, double newMaximum)
{
    lock (this)
    {
        if (_selfChanging) return;
        _selfChanging = true;

        if (newMaximum < Minimum)
        {
            IsDirectionReversed = !IsDirectionReversed;

            Maximum = Minimum;
            newMaximum = Maximum;
            Minimum = newMaximum;
        }

        if ((oldMaximum - Minimum) <= 0) oldMaximum = Minimum + 1;

        Value *= (newMaximum - Minimum) / (oldMaximum - Minimum);

        base.OnMaximumChanged(oldMaximum, newMaximum);

        _selfChanging = false;
    }
}

protected override void OnValueChanged(double oldValue, double newValue)
{
    //base.OnValueChanged(oldValue, newValue);
}

1 个答案:

答案 0 :(得分:0)

我能够使用辅助值来解决这个问题。

private double _oldValue;
protected override void OnValueChanged(double oldValue, double newValue)
{
    _oldValue = oldValue; // store previous values so we can later fix issues

    base.OnValueChanged(oldValue, newValue);
}

在计算中

// if (newMaximum < Value) // this will never be true because if value is bigger than newMaximum 
                           // slider cuts the Value before we reach here.

if (newMaximum > Value) // in case newMaximum was bigger than value
                        // that means we are safe to use original value
                        // if newMaximum is equal to Value that means 
                        // slider has possibly changed the value we should use _oldValue
    _oldValue = Value;

Value = _oldValue * (newMaximum - Minimum) / (oldMaximum - Minimum);

我做了这个,滑块保持比例。无论我改变最大值或最小值有多快。结果是正确的。令人惊讶的是,这里没有竞争条件。

当最小边界变化时,固定比例的逻辑相同。

if (newMinimum < Value)
    _oldValue = Value;

Value = _oldValue * (Maximum - newMinimum) / (Maximum - oldMinimum);