1

在 Silverlight 中没有 DependencyObject.CoerceValue。我正在寻找一种替代方法,也可以在 Silverlight 中执行以下 WPF 代码。

情况:有一个类Range,它有几个DependencyProperty: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 的解决方法。我在 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。而这正是我束手无策的位置。

如何在 MinimumChanged 上提高 LowerValue、UpperValue 和 Maximum 的强制?还是有另一种方法来确保初始化的顺序无关紧要并且所有属性都设置正确(假设条件得到满足)?

提前致谢!

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 回答