添加集合项时,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 设计器中进行重新呈现。
首先,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>());
}