WPF:动态连接画布上的矩形与路径之间

本文关键字:路径 之间 动态 连接 WPF | 更新日期: 2023-09-27 18:11:00

这是我第一次发帖,所以请宽容我…

确实有一些帖子展示了如何将行连接到块,但这一个略有不同。网格动态地放置在画布上。我想要一条线连接的网格从哪里按下按钮到新的网格,放在画布上。然而,下面的代码不起作用。我为这个问题纠结了很长时间。
完全是偶然的,我发现在按钮事件处理程序中抛出的Messagebox将允许它工作。我认为这是从线程运行在不同的时间,但在搞乱了task.delay/thread.sleep/async/await我找不到解决方案。
我使用自定义类是因为这是大型程序的简化版本,我希望在我的示例中具有类似的功能,以反映可能的错误,但省略不必要的部分。我这是最后一招,提前感谢你提供的任何帮助。首先是CS代码

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            Grid1 g = myCanvas.CreateGrid();
            ContentControl1 cc = myCanvas.CreateCC();
            Button1 b = myCanvas.CreateButton1();
            Grid1.SetColumn(cc, 0);
            Grid1.SetRow(cc, 0);
            Grid1.SetColumn(b, 1);
            Grid1.SetRow(b, 1);
            g.Children.Add(cc);
            g.Children.Add(b);
            Canvas1.SetLeft(g, 500);
            Canvas1.SetTop(g, 5);
            myCanvas.Children.Add(g);
        }
    }
    public class Button1 : Button
    {
        protected override void OnClick()
        {
            Grid1 old_g = (Grid1)VisualTreeHelper.GetParent(this as DependencyObject);
            Canvas1 cnv = (Canvas1)VisualTreeHelper.GetParent(old_g as DependencyObject);
            Grid1 g = cnv.CreateGrid();
            ContentControl1 cc = cnv.CreateCC();
            Button1 b = cnv.CreateButton1();
            Grid1.SetColumn(cc, 0);
            Grid1.SetRow(cc, 0);
            Grid1.SetColumn(b, 1);
            Grid1.SetRow(b, 1);
            g.Children.Add(cc);
            g.Children.Add(b);
            Canvas1.SetLeft(g, 500);
            Canvas1.SetTop(g, cnv.Children.Count * 120);
            cnv.Children.Add(g);
            cnv.ConnectGrids(old_g, g);
        }

    }
    public class Canvas1 : Canvas
    {
        public Grid1 CreateGrid()
        {
            Grid1 g = new Grid1() { Width = 100, Height = 20, Background = Brushes.White };
            g.HorizontalAlignment = HorizontalAlignment.Center;
            g.VerticalAlignment = VerticalAlignment.Center;
            g.ShowGridLines = false;
            ColumnDefinition colDef1 = new ColumnDefinition();
            ColumnDefinition colDef2 = new ColumnDefinition() { Width = new GridLength(20) };
            g.ColumnDefinitions.Add(colDef1);
            g.ColumnDefinitions.Add(colDef2);
            RowDefinition rowDef1 = new RowDefinition();
            g.RowDefinitions.Add(rowDef1);
            return g;
        }
        public ContentControl1 CreateCC()
        {
            ContentControl1 cc = new ContentControl1()
            {
                VerticalContentAlignment = VerticalAlignment.Stretch,
                HorizontalContentAlignment = HorizontalAlignment.Stretch,
                BorderBrush = Brushes.BlueViolet,
            };
            return cc;
        }
        public Button1 CreateButton1()
        {
            Button1 b = new Button1()
            {
                VerticalContentAlignment = VerticalAlignment.Stretch,
                HorizontalContentAlignment = HorizontalAlignment.Stretch,
                BorderBrush = Brushes.Red
            };
            return b;
        }
        public void ConnectGrids(Grid1 g1, Grid1 g2)
        {
            Canvas1 cnv = (Canvas1)VisualTreeHelper.GetParent(g1 as DependencyObject);
            Transform transform1 = (Transform)g1.TransformToVisual(cnv as Visual);
            Transform transform2 = (Transform)g2.TransformToVisual(cnv as Visual);
            Point StartPoint1 = transform1.Transform(new Point(g1.Width, g1.Height / 2.0));
            Point EndPoint1 = transform2.Transform(new Point(g2.Width, g2.Height / 2.0));

            var lineGeometry = new LineGeometry()
            {
                StartPoint = StartPoint1,
                EndPoint = EndPoint1
            };
            var path = new Path()
            {
                Data = lineGeometry,
                Stroke = new SolidColorBrush(Colors.Black),
            };
            cnv.Children.Add(path);
        }
    }
    public class ContentControl1 : ContentControl
    {
    }
    public class Grid1 : Grid
    {
    }

}
然后是xaml:
<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local ="clr-namespace:WpfApplication1"
        Title="MainWindow" Height="1000" Width="1000">
    <DockPanel>
        <Button DockPanel.Dock="Top" Width="100" Height="20" Content="Start" Click="Button_Click"/>
        <ScrollViewer HorizontalScrollBarVisibility="Visible" Width="901" x:Name="_scrollViewer" Margin="0,5,0,25">
            <local:Canvas1 Background="Gray" Height="1000" Width="1000" x:Name="myCanvas"/>
        </ScrollViewer>
    </DockPanel>
</Window>

如何将网格与路径成功连接?

WPF:动态连接画布上的矩形与路径之间

我喜欢我解决了这个问题/讨厌我必须回答我自己的愚蠢问题…

如此简单。UpdateLayout()。对象在渲染之前不会改变位置,所以线条会回到原来的位置。