在正确实现INotifyPropertyChanged
的WPF数据绑定中,应该强制执行GUI的渲染事件。不知怎的,我找到了一个没有的例子。我想将ObservableCollection<Point>
绑定到Points
的{{1}}属性。因此Polyline
只接受Points
我需要PointCollection
。每当Bining工作正常时,Converter就会创建一个PointCollection的新实例。但是当我在转换器中创建一个私有字段(类型为IValueConverter
)时,它存储数据并对其应用更改(例如添加或删除PointCollection)
),那么Point
不会呈现!
XAML:
Polyline
转换器:
<canvas>
<Polyline Stroke="blue" Width="Auto" Height="Auto" Points="{Binding points, Converter=DataPointConverter}"></Polyline>
</canvas>
事实上,这些点已正确添加到class DataPointConverter : IValueConverter
{
private PointCollection privatePoints;
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
IEnumerable<Point> _enumerable = value as IEnumerable<Point>;
if (_enumerable == null)
{
throw new InvalidOperationException("Source collection must be of type IEnumerable<Point>");
}
if (privatePoints == null)
{
privatePoints = new PointCollection(_enumerable);
INotifyCollectionChanged _notifyCollectionChanged = _enumerable as INotifyCollectionChanged;
if (_notifyCollectionChanged != null)
{
_notifyCollectionChanged.CollectionChanged += this.Source_CollectionChanged;
}
}
return privatePoints;
//next line would work! but i don't want to copy the entire list every time
//return new PointCollection(_enumerable);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
private void Source_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
for (int i = 0; i < e.NewItems.Count; i++)
{
privatePoints.Insert(e.NewStartingIndex + i, (Point)e.NewItems[i]);
}
break;
case NotifyCollectionChangedAction.Move:
for (int i = 0; i < e.NewItems.Count; i++)
{
privatePoints.RemoveAt(e.OldStartingIndex);
privatePoints.Insert(e.NewStartingIndex + i, (Point)e.NewItems[i]);
}
break;
case NotifyCollectionChangedAction.Remove:
for (int i = 0; i < e.OldItems.Count; i++)
{
privatePoints.RemoveAt(e.OldStartingIndex);
}
break;
case NotifyCollectionChangedAction.Replace:
for (int i = 0; i < e.NewItems.Count; i++)
{
privatePoints[e.NewStartingIndex + i] = (Point)e.NewItems[i];
}
break;
case NotifyCollectionChangedAction.Reset:
privatePoints.Clear();
break;
}
}
(我可以在强制渲染事件时看到它们,例如更改Polyline
的{{1}}。但在我看来,绑定应该触发渲染。 (我甚至检查了Stroke
)
我做错了吗?或者这是.NET Framework的未记录的“功能”吗?
我的消息来源:基本上我实施了Tamir Khason在blog中所写的内容。 (他为donwnload提供的解决方案不起作用。他永远不会从字典中返回值,但始终是新创建的集合)
答案 0 :(得分:0)
请你试试吗
<canvas>
<Polyline Stroke="blue" Width="Auto" Height="Auto" Points="{Binding points,Mode=TwoWay,updatesourcetrigger=propertychanged, Converter=DataPointConverter}"> </Polyline>
</canvas>