添加集合项目时,OnRender不会调用?

添加集合项目时,OnRender不会调用?

问题描述:

我有一个用于执行动态数据呈现的自定义控件。此控件包含一组DataPoint对象,并且每个DataPoint都基于其位置(控制点绘制在OnRender方法中)呈现在控件中。添加集合项目时,OnRender不会调用?

自定义控件包含许多DependencyProperties影响渲染的图像,因此具有FrameworkPropertyMetadata描述了控制应呈现,如果属性的变化:

public static readonly DependencyProperty DataPointsProperty = 
    DependencyProperty.Register(
     "DataPoints",          //Property Name 
     typeof(List<DataPoint>),       //CLR-Property Type 
     typeof(MyCustomControl),       //Custom Control Type 
     new FrameworkPropertyMetadata(
      new List<DataPoint>(),       //Default Value. 
      FrameworkPropertyMetadataOptions.AffectsRender //Re-render if changed 
     ) 
    ); 

遗憾的是,重新渲染确实NOT发生在新的DataPoint时,将添加到此集合中。

如何添加新的DataPoint时,如何配置我的自定义控件以便调用OnRender方法?

除了程序的运行时间以外,重新呈现必须发生在WPF设计器中。

+1

没有这个**大胆**也人们可以很好地阅读这个问题。我已经编辑了你的问题。 – 2014-09-24 18:45:47

首先,List<T>不支持更改通知,而WPF的内置集合做了支持更改通知并非来自List<T>。我建议您使用IList<T>IEnumerable<T>作为您的房产类型。第二,每当新的集合被分配到DataPoints(验证它实现INotifyCollectionChanged后),并且使用该处理程序调用InvalidateVisual()时,您将需要添加集合更改处理程序。最简单的方法是在注册DataPoints依赖项属性时指定属性更改回调。

public static readonly DependencyProperty DataPointsProperty = 
    DependencyProperty.Register(
     "DataPoints",          //Property Name 
     typeof(IList<DataPoint>),       //CLR-Property Type 
     typeof(MyCustomControl),       //Custom Control Type 
     new FrameworkPropertyMetadata(
      default(IList<DataPoint>),      //Default Value. 
      FrameworkPropertyMetadataOptions.AffectsRender, //Re-render if changed, 
      OnDataPointsPropertyChanged 
     ) 
    ); 

private static void OnDataPointsPropertyChanged(
    DependencyObject d, 
    DependencyPropertyChangedEventArgs e) 
{ 
    var control = (MyCustomControl)d; 

    var oldValue = e.OldValue as INotifyCollectionChanged; 
    var newValue = e.NewValue as INotifyCollectionChanged; 

    if (oldValue != null) 
     oldValue.CollectionChanged -= control.OnDataPointsCollectionChanged; 

    if (newValue != null) 
     newValue.CollectionChanged += control.OnDataPointsCollectionChanged; 
} 

private void OnDataPointsCollectionChanged(
    object s, 
    NotifyCollectionChangedEventArgs e) 
{ 
    this.InvalidateVisual(); 
} 

最后,不要指定默认属性值的集合实例:这将导致所有实例共享相同的集合(除非分配一个新的)。相反,初始化您的构造函数中的属性:

public MyCustomControl() 
{ 
    // ... 
    SetCurrentValue(DataPointsProperty, new ObservableCollection<DataPoint>()); 
} 
+1

+1提醒我在初始化引用类型依赖项属性时使用SetCurrentValue而不是本地值。 – Clemens 2014-09-24 19:13:34

+0

太棒了!有用。顺便说一下,如果集合具有在XAML中指定的项目,则“IList”将不起作用,因为它只允许1个子元素(并且该子元素不是列表项)。但是,将其更改为“ObservableCollection”允许我在XAML中指定项目。 – 2014-09-24 19:53:17

+1

非泛型'IList'应该在Xaml中正常工作,但'IList '可能不会。我相信Xaml只支持'IList'和'IAddChild'。 – 2014-09-25 13:38:12