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;
    }
上一篇
下一篇