2011-07-01 3 views
1

SilverlightにはDependencyObject.CoerceValueはありません。私はWPFコードをSilverlightでもやっています。Silverlight:Missing DependencyObject.CoerceValue

状況: Rangeには、いくつかのDependencyProperties:MinimumProperty、MaximumProperty、LowerValueProperty、およびUpperValuePropertyがあります。

最小値は最大値より大きくなることはありません。最小値は最小値より小さくなることはありません。さらに、LowerValueとUpperValueは最小値と最大値の間にある必要がありますが、LowerValueは常にUpperValueより小さくなければなりません。

すべてDependencyPropertiesは(WPFで)このように実装されています

public static new readonly DependencyProperty MinimumProperty = 
    DependencyProperty.Register("Minimum", 
    typeof(double), 
    typeof(Range), 
    new FrameworkPropertyMetadata(0d, 
     new PropertyChangedCallback(Range.OnMinimumChanged), 
     new CoerceValueCallback(Range.CoerceMinimum)), 
    new ValidateValueCallback(Range.ValidateMinimum)); 

public new double Minimum 
    { 
     get { return (double)base.GetValue(MinimumProperty); } 
     set { base.SetValue(MinimumProperty, value); } 
    } 

WPFでの強制は、そのように行われます。

private static object CoerceMinimum(DependencyObject source, object value) 
{ 
    Range r = source as Range; 
    double maximum = r.Maximum; 
    double val = (double)value; 
    if (val > maximum) 
    { 
    return maximum; 
    } 
    return value; 
} 

PropertyChangedCallbackは、次のようになります。

private static void OnMinimumChanged(DependencyObject source, DependencyPropertyChangedEventArgs e) 
{ 
    Range r = source as Range; 
    r.CoerceValue(LowerValueProperty); 
    r.CoerceValue(UpperValueProperty); 
    r.CoerceValue(MaximumProperty); 
} 

この場合、ValidateValueCallbackは重要ではありません。他のコールバックは、示されているコードに似ています。

これはWPFではうまく動作します。たとえば、(XAMLで)

<Range LowerValue="12" Minimum="10" UpperValue="15" Maximum="20" /> 

すべての値が正しく設定されています。順序は関係ありません!

しかし、Silverlightでは動作しません。

最初の手順は、CoerceValueCallbackの回避策です。

private static void OnMinimumChanged(DependencyObject source, DependencyPropertyChangedEventArgs e) 
{ 
    Range r = source as Range; 
    double newVal = (double)e.NewValue; 
    double coercedVal = (double)CoerceMinimum(source, newVal); 
    if (coercedVal != newVal) 
    { 
    r.Minimum = coercecVal; 
    return; 
    } 

    r.CoerceValue(LowerValueProperty); 
    r.CoerceValue(UpperValueProperty); 
    r.CoerceValue(MaximumProperty); 
} 

今最小の値に設定されている場合は、CoerceMinimumがまだ実行され、最小、強制はよくやった:私はこのように、PropertyChangedCallbackで強制を上げます。

しかし、DependencyObjectにはCoerceValueメソッドがないため、最後の3行はコンパイルされません。そして、まさにこれは、私が知恵の終わりにいる位置です。

MinimumChangedでLowerValue、UpperValue、Maximumの強制をどのようにして発生させるのですか? また、初期化の順序が重要でなく、すべてのプロパティが正しく設定されていることを確認する別の方法があります(条件が満たされていると仮定します)。

ありがとうございます!

答えて

0

私は解決策を得ました:)確かに、それはまだ完了していません。私はまだすべての可能な注文をデバッグしているが、私はほとんど完了したと思う。

私はLowerValueのためだけのコードを投稿し、他はほぼ同じです。

  • はCoerceUpperValueChangedと CoerceLowerValueChangedを上げOnUpperValueChanged。
  • OnMinimumChanged raise CoerceMinimum、 CoerceUpperValueChangedおよび CoerceLowerValueChanged。
  • OnMaximumChanged raise CoerceMaximum、CoerceUpperValueChangedおよびCoerceLowerValueChanged。

最小と最大の強制は簡単です。新しい値がMaximum(またはMinimumより小さい)より大きい場合、Maximum(またはMinimum)をとり、そうでない場合は新しい値をとります。ここで

はコードです:

private static void OnLowerValueChanged(DependencyObject source, DependencyPropertyChangedEventArgs e) 
{ 
    Range r = source as Range; 

    if (r._levelsFromRootCall == 0) 
    { 
    r._requestedLowerVal = (double)e.NewValue; 
    } 

    r._levelsFromRootCall++; 
    r.CoerceLowerValue(); 

    r.CoerceUpperValue(); 
    r._levelsFromRootCall--; 
} 

private void CoerceLowerValue() 
{ 
    double minimum = this.Minimum; 
    double maximum = this.Maximum; 
    double lowerVal = this.LowerValue; 
    double upperVal = this.UpperValue; 
    if (lowerVal != _requestedLowerVal && _requestedLowerVal >= minimum && _requestedLowerVal <= maximum) 
    { 
    if (_requestedLowerVal <= upperVal) 
    { 
     base.SetValue(LowerValueProperty, _requestedLowerVal); 
    } 
    else 
    { 
     base.SetValue(LowerValueProperty, upperVal); 
    } 
    } 
    else 
    { 
    if (lowerVal < minimum) 
    { 
     base.SetValue(LowerValueProperty, minimum); 
    } 
    else if (lowerVal > upperVal || _requestedLowerVal > upperVal) 
    { 
     base.SetValue(LowerValueProperty, upperVal); 
    } 
    else if (lowerVal > maximum) 
    { 
     base.SetValue(LowerValueProperty, maximum); 
    } 
    } 
}