我有一个用于执行动态数据呈现的自定义控件。此控件包含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
添加到此集合时,重新渲染会发生 NOT 。
如何配置我的自定义控件,以便在添加新的OnRender
时调用DataPoint
方法?
除了程序的运行时间之外,还必须在WPF设计器中进行重新渲染。
答案 0 :(得分:4)
首先,List<T>
不支持更改通知,而 支持更改通知的WPF内置集合并非来自List<T>
。我建议您使用IList<T>
或IEnumerable<T>
作为您的媒体资源类型。
其次,只要将新集合分配给DataPoints
(在验证它实现INotifyCollectionChanged
之后),就需要添加集合更改处理程序,并使用该处理程序调用{{1}}。最简单的方法是在注册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();
}