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

本文关键字:调用 OnRender 集合 添加 | 更新日期: 2023-09-27 18:24:11

我有一个用于执行动态数据呈现的自定义控件。 此控件包含 DataPoint 对象的集合,每个DataPoint都根据其位置在控件中呈现(点在 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
        )
    );

遗憾的是,将新DataPoint添加到集合时不会发生重新呈现。

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

除了程序的运行时之外,还必须在 WPF 设计器中进行重新呈现。

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

首先,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>());
}