wpf 点连线

xaml

<Grid
Background="#000123" MouseLeftButtonDown="UIElement_OnMouseLeftButtonDown" MouseMove="UIElement_OnMouseMove" PreviewMouseLeftButtonUp="UIElement_OnPreviewMouseLeftButtonUp">
<UniformGrid
Margin="25"
Columns="3" Rows="3">
<UniformGrid.Resources>
<ControlTemplate x:Key="PointControlTemplate">
<Grid>
<Ellipse
Width="35" Height="35"
Fill="#3B87E7" Opacity=".3">
<Ellipse.Effect>
<DropShadowEffect
BlurRadius="5" ShadowDepth="3"
Color="#3B87E7" />
</Ellipse.Effect>
</Ellipse>
<Ellipse
Width="15" Height="15"
Fill="#FFFEFF" Opacity=".8" />
</Grid>
</ControlTemplate>
<Style TargetType="ContentControl">
<Setter Property="Template" Value="{StaticResource PointControlTemplate}" />
</Style>
</UniformGrid.Resources>
<ContentControl />
<ContentControl />
<ContentControl />
<ContentControl />
<ContentControl />
<ContentControl />
<ContentControl />
<ContentControl />
<ContentControl />
</UniformGrid>
</Grid>

cs

private readonly HashSet<ContentControl> points = new(); // 已经用过的点
private Line? currentLine = null; // 当前正在绘制的线
// 创建一条线
private static Line CreateLine(Point startPoint, Color color)
{
var line = new Line();
line.X1 = line.X2 = startPoint.X;
line.Y1 = line.Y2 = startPoint.Y;
line.Fill = line.Stroke = new SolidColorBrush(color);
line.StrokeThickness = 10;
line.StrokeStartLineCap = line.StrokeEndLineCap = PenLineCap.Round;
line.IsHitTestVisible = false; // 重要,不设置的话鼠标当前元素就是这条 line, 而不是 point 了
return line;
}
// 返回当前点的中点
private static Point GetPointCenter(ContentControl point, Grid grid)
{
var center = point.TranslatePoint(new Point(point.ActualWidth / 2, point.ActualHeight / 2), grid);
return center;
}
// 创建一条新线
private void CreateCurrentLine(ContentControl point, Grid grid)
{
// 获取 point 中间的坐标
var startPoint = GetPointCenter(point, grid);
var line = CreateLine(startPoint, Colors.DodgerBlue);
grid.Children.Add(line);
this.currentLine = line;
}
// 完成当前线
private void FinishedCurrentLine(ContentControl point, Grid grid)
{
if (this.currentLine == null)
{
return;
}
var endPoint = GetPointCenter(point, grid);
this.currentLine.X2 = endPoint.X;
this.currentLine.Y2 = endPoint.Y;
this.points.Add(point);
}
private void UIElement_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.Source is ContentControl point && sender is Grid grid)
{
// 开始一条新的线
this.CreateCurrentLine(point, grid);
}
}
private void UIElement_OnMouseMove(object sender, MouseEventArgs e)
{
if (this.currentLine == null || sender is not Grid grid)
{
// 当前没有正在绘制的线, 直接返回
return;
}
if (e.Source is ContentControl point && !this.points.Contains(point))
{
// 完成当前的线
this.FinishedCurrentLine(point, grid);
// 开始一条新的线
this.CreateCurrentLine(point, grid);
}
else
{
var position = e.GetPosition(grid);
this.currentLine.X2 = position.X;
this.currentLine.Y2 = position.Y;
}
}
private void UIElement_OnPreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
// 清空所有已画的线条
if (sender is not Grid grid)
{
return;
}
var lines = grid.Children.OfType<Line>().ToArray();
Array.ForEach(lines, it => grid.Children.Remove(it));
this.points.Clear();
this.currentLine = null;
}
上一篇
下一篇