[英]C# wpf how to draw rectangle on polyline points
I am trying to draw a polyline on a canvas which will have rectangle on each point. 我正在尝试在画布上画一条折线,在每个点上都将具有矩形。 The Polyline is bound to a collection of points from the ViewModel.
折线绑定到ViewModel中的点集合。
When I try to set DataTemplate
for each point (like below) it shows no rectangle on polyline points. 当我尝试为每个点设置
DataTemplate
时(如下所示),它在折线点上没有显示矩形。
Is there some way to display rectangle on polyline points? 有什么办法可以在折线点上显示矩形?
Later I want to adjust the polyline by dragging these points. 稍后,我想通过拖动这些点来调整折线。
<Polyline Points="{Binding EdgePoints, Converter={StaticResource pointCollectionConverter}}" StrokeThickness="2">
<Polyline.Resources>
<DataTemplate DataType="{x:Type Point}">
<Rectangle Width="20" Height="20" Fill="Black"/>
</DataTemplate>
</Polyline.Resources>
</Polyline>
Here is example where I want to draw rectangles. 这是我要绘制矩形的示例。
You could have a view model like the one shown below. 您可能具有如下所示的视图模型。 Besides the obvious parts, it attaches/detaches a PropertyChanged handler to/from each
Vertex
in order to fire the PropertyChanged event for the Vertices
property. 除了明显的部分外,它还会向每个
Vertex
附加/分离一个PropertyChanged处理程序,以触发Vertices
属性的PropertyChanged事件。 This is necessary to update the Polyline's Point Binding. 这是更新折线的点绑定所必需的。
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class Vertex : ViewModelBase
{
private Point point;
public Point Point
{
get { return point; }
set { point = value; OnPropertyChanged(); }
}
}
public class ViewModel : ViewModelBase
{
public ViewModel()
{
Vertices.CollectionChanged += VerticesCollectionChanged;
}
public ObservableCollection<Vertex> Vertices { get; }
= new ObservableCollection<Vertex>();
private void VerticesCollectionChanged(
object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Add)
{
foreach (var item in e.NewItems.OfType<INotifyPropertyChanged>())
{
item.PropertyChanged += VertexPropertyChanged;
}
}
else if (e.Action == NotifyCollectionChangedAction.Remove)
{
foreach (var item in e.OldItems.OfType<INotifyPropertyChanged>())
{
item.PropertyChanged -= VertexPropertyChanged;
}
}
OnPropertyChanged(nameof(Vertices));
}
private void VertexPropertyChanged(object sender, PropertyChangedEventArgs e)
{
OnPropertyChanged(nameof(Vertices));
}
}
The Vertices to PointCollection converter could look like this: 顶点到PointCollection转换器可能看起来像这样:
public class VerticesConverter : IValueConverter
{
public object Convert(
object value, Type targetType, object parameter, CultureInfo culture)
{
var vertices = value as IEnumerable<Vertex>;
return vertices != null
? new PointCollection(vertices.Select(v => v.Point))
: null;
}
public object ConvertBack(
object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
The view would use a Polyline and an ItemsControl. 该视图将使用折线和ItemsControl。 The ItemsTemplate would declare a
Thumb
element that handles the dragging of vertex points. ItemsTemplate将声明一个
Thumb
元素来处理顶点的拖动。
<Canvas>
<Canvas.Resources>
<local:VerticesConverter x:Key="VerticesConverter"/>
<Style x:Key="ThumbStyle" TargetType="Thumb">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Thumb">
<Rectangle Fill="Transparent" Stroke="Red"
Width="10" Height="10" Margin="-5,-5"/>
</ControlTemplate>
</Setter.Value>
</Setter>
<EventSetter Event="DragDelta" Handler="ThumbDragDelta"/>
</Style>
</Canvas.Resources>
<Polyline Points="{Binding Vertices, Converter={StaticResource VerticesConverter}}"
Stroke="DarkBlue" StrokeThickness="3" StrokeLineJoin="Round"/>
<ItemsControl ItemsSource="{Binding Vertices}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding Point.X}"/>
<Setter Property="Canvas.Top" Value="{Binding Point.Y}"/>
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Thumb Style="{StaticResource ThumbStyle}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Canvas>
Finally, the Thumb's DragDelta handler: 最后,Thumb的DragDelta处理程序:
private void ThumbDragDelta(object sender, DragDeltaEventArgs e)
{
var vertex = (Vertex)((Thumb)sender).DataContext;
vertex.Point = new Point(
vertex.Point.X + e.HorizontalChange,
vertex.Point.Y + e.VerticalChange);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.