1

Silverlight には、DependencyObject.CoerceValue はありません。Silverlight でも次の WPF コードを実行するための代替手段を探しています。

状況: いくつかの DependencyProperties (MinimumProperty、MaximumProperty、LowerValueProperty、および UpperValueProperty) を持つクラス Range があります。

最小値が最大値よりも大きくなることはなく、最大値が最小値よりも小さくなることはありません。さらに、LowerValue と UpperValue は Minimum と Maximum の間にある必要がありますが、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 の回避策です。次のように、PropertyChangedCallback で強制を発生させます。

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

ここで Minimum が値に設定されている場合、CoerceMinimum は引き続き実行され、Minimum-Coercion は適切に実行されます。

ただし、DependencyObject には CoerceValue-Method がないため、最後の 3 行はコンパイルされません。そして、まさにこれが私が途方に暮れている立場です。

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

前もって感謝します!

4

1 に答える 1

0

私は解決策を得ました:)確かに、それはまだ完了していません。考えられるすべての注文をまだデバッグする必要がありますが、ほとんどは既に完了していると思います。

LowerValue のコードのみを投稿します。他はほぼ同じです。

  • OnUpperValueChanged は CoerceUpperValueChanged と CoerceLowerValueChanged を発生させます。
  • OnMinimumChanged は、CoerceMinimum、CoerceUpperValueChanged、および CoerceLowerValueChanged を発生させます。
  • OnMaximumChanged は、CoerceMaximum、CoerceUpperValueChanged、および CoerceLowerValueChanged を発生させます。

最小値と最大値の強制は簡単です。新しい値が最大値より大きい (または最小値より小さい) 場合は、最大値 (または最小値) を取得し、それ以外の場合は新しい値を取得します。

コードは次のとおりです。

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);
    }
  }
}
于 2011-07-04T10:33:28.747 に答える