2017-01-02 3 views
0

Я создаю слайдер, который сохраняет соотношение текущего значения при изменении максимального или минимального значения.Правильное соотношение значения ползунка при изменении границы

Вот изображение, показывающее, как я корректирую соотношение стоимости на слайдере.

enter image description here

(Второй слайдер расширяется, чтобы лучше объяснить решение. Очевидно, что размер ползунка в виде приложения является фиксированной и только значения внутренне изменились.)

Это то, что вы видите в результате.

enter image description here

Формула я использую, чтобы установить соотношение довольно просто. Это формула используется при изменении 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); 
} 

ответ

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); 
Смежные вопросы