首先,您需要创建自定义类PointCollection
:
public class PointCollection : ObservableCollection<Point>
{
public PointCollection()
{
}
public PointCollection(IEnumerable<Point> points) : base(points)
{
}
}
其次,您需要创建自定义Polyline
:
public class PolylineDynamic : Shape
{
private Geometry _polylineGeometry = Geometry.Empty;
public static readonly DependencyProperty PointsProperty = DependencyProperty.Register(nameof(Points), typeof(PointCollection), typeof(PolylineDynamic), new FrameworkPropertyMetadata(PointsChanged));
private static void PointsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((PolylineDynamic)d).PointsChanged(e);
}
private void PointsChanged(DependencyPropertyChangedEventArgs e)
{
if (e.OldValue is PointCollection oldPoints)
oldPoints.CollectionChanged -= OnPointsChanged;
if (e.NewValue is PointCollection newPoints)
newPoints.CollectionChanged += OnPointsChanged;
UpdatePolyline();
}
public PointCollection Points
{
get => (PointCollection)GetValue(PointsProperty);
set => SetValue(PointsProperty, value);
}
public static readonly DependencyProperty FillRuleProperty = DependencyProperty.Register(nameof(FillRule), typeof(FillRule), typeof(PolylineDynamic), new FrameworkPropertyMetadata(FillRule.EvenOdd));
public FillRule FillRule
{
get => (FillRule)GetValue(FillRuleProperty);
set => SetValue(FillRuleProperty, value);
}
protected override Geometry DefiningGeometry => _polylineGeometry;
private void OnPointsChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
var aPoint = e.NewItems.OfType<Point>().Single();
Add(aPoint, e.NewStartingIndex);
break;
case NotifyCollectionChangedAction.Remove:
Remove(e.OldStartingIndex);
break;
case NotifyCollectionChangedAction.Replace:
var rPoint = e.NewItems.OfType<Point>().Single();
Replace(rPoint, e.NewStartingIndex);
break;
}
}
protected void UpdatePolyline()
{
if (Points == null || Points.Count < 2)
_polylineGeometry = Geometry.Empty;
else
{
var pGeometry = GetPathGeometry();
for (var i = 0; i < Points.Count; i++)
{
if (i == 0)
continue;
var startPoint = Points[i - 1];
var point = Points[i];
var figure = new PathFigure { StartPoint = startPoint };
figure.Segments.Add(new LineSegment(point, true));
pGeometry.Figures.Add(figure);
}
}
}
private void Add(Point point, int index)
{
var pGeometry = GetPathGeometry();
if (pGeometry.Figures.Count == 0)
{
UpdatePolyline();
return;
}
if (index == Points.Count - 1)
{
var segment = new LineSegment(point, true);
var figure = new PathFigure { StartPoint = Points[index - 1] };
figure.Segments.Add(segment);
pGeometry.Figures.Add(figure);
}
else if (index == 0)
{
var segment = new LineSegment(Points[1], true);
var figure = new PathFigure { StartPoint = point };
figure.Segments.Add(segment);
pGeometry.Figures.Insert(0, figure);
}
else
{
var leftFigure = new PathFigure { StartPoint = Points[index - 1] };
leftFigure.Segments.Add(new LineSegment(point, true));
var rightFigure = new PathFigure { StartPoint = point };
rightFigure.Segments.Add(new LineSegment(Points[index + 1], true));
pGeometry.Figures.Insert(index - 1, leftFigure);
pGeometry.Figures.Insert(index, rightFigure);
}
InvalidateVisual();
}
private void Remove(int index)
{
var pGeometry = GetPathGeometry();
if (!pGeometry.Figures.Any())
{
_polylineGeometry = Geometry.Empty;
InvalidateVisual();
return;
}
if (index == Points.Count - 1 || index == 0)
pGeometry.Figures.RemoveAt(index);
else
{
var leftFigure = pGeometry.Figures[index - 1];
var rightFigure = pGeometry.Figures[index];
pGeometry.Figures.RemoveAt(index - 1);
rightFigure.StartPoint = ((LineSegment)leftFigure.Segments.Single()).Point;
}
InvalidateVisual();
}
private void Replace(Point point, int index)
{
var pGeometry = GetPathGeometry();
if (index == 0)
pGeometry.Figures[0].StartPoint = point;
else if (index == Points.Count - 1)
ReplaceSegment(pGeometry.Figures[index - 1], point);
else
{
ReplaceSegment(pGeometry.Figures[index - 1], point);
pGeometry.Figures[index].StartPoint = point;
}
InvalidateVisual();
}
private void ReplaceSegment(PathFigure figure, Point point)
{
figure.Segments.Clear();
figure.Segments.Add(new LineSegment(point, true));
}
private PathGeometry GetPathGeometry()
{
if (_polylineGeometry is PathGeometry pathGeometry)
return pathGeometry;
else
{
pathGeometry = new PathGeometry { FillRule = FillRule };
_polylineGeometry = pathGeometry;
return pathGeometry;
}
}
}
如果您需要更多功能,可以添加更多)