延迟“渲染”WPF / Silverlight依赖属性?

时间:2009-09-23 13:08:25

标签: wpf silverlight data-binding dependency-properties

有没有办法知道第一次通过XAML绑定访问依赖属性,所以我可以在需要时实际“渲染”属性的值?

我有一个对象(从Control派生的类),它有几个PointCollection依赖属性,可能包含100或1000个点。每个属性可以不同的方式排列点以用于不同类型的形状(折线,多边形等 - 它比这更复杂,但你明白了)。通过模板,不同的XAML对象使用TemplateBinding来访问这些属性。由于我的对象使用模板,我永远不知道XAML形状可能用于我的对象 - 所以我永远不知道它们可能绑定或不绑定的属性。我只想在实际需要时填写这些PointCollections。

通常在.NET中我只是在属性的getter中有一些逻辑,但这些都被XAML数据绑定所绕过。

我需要一个WPF和Silverlight兼容的解决方案。

我喜欢一种解决方案,可以避免对象用户的任何额外复杂性。


更新

我发现这样做的一种方法是使用Value Converters。在我的情况下,我有多个点集合。有一个主要的dep。包含通常数据形状的属性。在其他领域/环境中需要两种替代形状才能重复使用。

起初我有3个dep。道具。但是,我可能只有一个属性(通常的形状)并使用转换后的值将点转换为我的其他2个所需形状。这样做我只在控件中创建一组点。将点转换为次要形状的费用仅在使用时产生。现在我的主要控件不需要预测数据如何查找控件中抛出的每个可能的模板 - 现在它是模板设计者的问题。


更新2

当然,建议使用INotifyPropertyChanged和常规属性来处理此问题。

2 个答案:

答案 0 :(得分:3)

您不一定必须使用依赖项属性来启用数据绑定。但是,如果源上的更改应传播到绑定的目标,则必须实现INotifyPropertyChanged。 “普通”.NET属性很容易延迟加载,可能是这样的:

PointCollection points

public PointCollection Points {
  get {
    return this.points ?? (this.points = CreatePoints());
  }
}

PointCollection CreatePoints() {
  // ...
}

我不确定如何使INotifyPropertyChanged适合您的控件,但是您的控件将数据提供给系统的其他部分听起来有点奇怪。也许您需要创建一个视图模型,其中包含您可以让控件数据绑定到的数据。

答案 1 :(得分:0)

如果我将你的问题解释为

  

如何在更改依赖项属性时收到通知?

这是正确的吗?我从你的短语“通常在.NET中,我只是在属性的getter中的一些逻辑,但这些被XAML数据绑定绕过”中得出这个。

如果我是正确的,那么你可以注册你自己的属性改变回调。它总是被称为。无论是谁造成了更改绑定,样式或触发器。以下代码段取自MSDN文章“Dependency Property Callbacks and Validation”:

public static readonly DependencyProperty CurrentReadingProperty = 

    DependencyProperty.Register(
        "CurrentReading",
        typeof(double),
        typeof(Gauge),
        new FrameworkPropertyMetadata(
            Double.NaN,
            FrameworkPropertyMetadataOptions.AffectsMeasure,
            new PropertyChangedCallback(OnCurrentReadingChanged),
            new CoerceValueCallback(CoerceCurrentReading)
        ),
        new ValidateValueCallback(IsValidReading)
    );
    public double CurrentReading
    {
      get { return (double)GetValue(CurrentReadingProperty); }
      set { SetValue(CurrentReadingProperty, value); }
    }

这里的内容是OnCurrentReadingChanged()方法。希望这有助于:)。