我正在创建滑块,以便在最大值或最小值更改时保持当前值的比率。
这是显示我如何修正滑块上的值比例的图片。
(扩展第二个滑块以更好地解释解决方案。显然,应用程序视图中滑块的大小是固定的,只有内部更改值。)
这就是你看到的结果。
用于修正比率的公式I非常简单。这是Maximum
值更改时使用的公式:
NewValue = OldValue * ((newMaximum - Minimum) / (oldMaximum - Minimum));
如果Minimum
值已更改:
NewValue = OldValue * ((Maximum - newMinimum) / (Maximum - oldMinimum));
(有一些事情需要考虑,例如防止除零。但这里的主题是偏离主题。)
现在看看问题何时出现。假设newMaximum
小于滑块的值。 遗憾的是滑块内部行为想要通过执行value = newMaximum
来纠正该值,因此这与我的计算冲突。
下图通过反向显示问题。第二个滑块是我想要的,但我得到了第三个滑块。
这是我尝试过的。 (代码简化)
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);
}
答案 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);