2017-01-02 6 views
0

最大値または最小値が変更されたときの現在の値の比率を保持するスライダを作成しています。境界が変更されたときのスライダの値の正確な比率

ここでは、スライダの値の比率をどのように補正しているかを示す画像を示します。

enter image description here

(第2スライダはよりよい解決策を説明するために展開されている。明らかに、アプリケーションビューのスライダーのサイズは固定と値のみが内部的に変更されている。)

これは、あなたが見るものです結果として。

enter image description here

私は比率を修正するために使用している数式は非常に簡単です。これはMaximum値が変更されたときに使用される式である:

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

そしてMinimum値が変更された場合には:

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

(そこゼロ除算を防ぐ例えば、考慮すべきいくつかのことがあるが、それです。オフトピックです)

ここで問題が発生したときを見てください。 newMaximumがスライダの値より小さいとします。 残念ながらスライダーの内部動作は、value = newMaximumを実行して値を修正したいので、これが私の計算と競合します。

次の図は、その逆を行って問題を示しています。 2番目のスライダーは私が望むものですが、3番目のスライダーを取得します。

enter image description here


これは私が試したものです。私はOnValueChangedをオーバーライドしていますが、スライダーをnewMaximumはあなたが画像で見ることができるようvalue = newMaximumを実行して、valueより小さいとき値を補正し続けるにもかかわらず

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); 
} 

(コードが簡略化されます)。 どうすれば修正できますか?


警告:次のコードは、あなたが頭痛与えるかもしれません!問題を説明しようとしましたが、理解していただきたいと思います。場合は、ここで私は現在持っている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); 
関連する問題