2013-06-11 19 views

回答

1

这里是一个快速和肮脏的实施:

表示连接类:

public partial class Connection 
{ 
    public MyBox Box1 { get; set; } 
    public MyBox Box2 { get; set; } 
    public Line Line { get; set; } 
} 

要创建一个新的连接,我使用的基本形式:来源,目的地和按钮的名称, :

<StackPanel Orientation="Horizontal" Grid.Row="3"> 
    <TextBox Width="100" Text="{Binding From,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" /> 
    <TextBlock Text=" ----> " /> 
    <TextBox Width="100" Text="{Binding To,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" /> 
    <Button Content="Connect" Click="Button_Click_2" /> 
</StackPanel> 

这里是处理:

public string From { get; set; } 
public string To { get; set; } 

private IList<Connection> connections = new List<Connection>(); 
private void Button_Click_2(object sender, RoutedEventArgs e) 
{ 
    MyBox box1 = boxes.Single(b => b.Header == From); 
    MyBox box2 = boxes.Single(b => b.Header == To); 

    Connection conn = new Connection { Box1 = box1, Box2 = box2, Line = new Line { StrokeThickness = 1, Stroke = Brushes.Black } }; 
    connections.Add(conn); 

    RefreshLinesPositions(); 

    panel.Children.Add(conn.Line); 
} 

而且RefreshLinesPositions代码:

private void RefreshLinesPositions() 
{ 
    foreach (Connection conn in connections) 
    { 
     Point p1 = conn.Box1.TranslatePoint(new Point(0, 0), panel); 
     Point p2 = conn.Box2.TranslatePoint(new Point(0, 0), panel); 

     double t1 = p1.Y; 
     double b1 = p1.Y + conn.Box1.ActualHeight; 
     double l1 = p1.X; 
     double r1 = p1.X + conn.Box1.ActualWidth; 

     double t2 = p2.Y; 
     double b2 = p2.Y + conn.Box2.ActualHeight; 
     double l2 = p2.X; 
     double r2 = p2.X + conn.Box2.ActualWidth; 

     if (r1 < l2) 
     { 
      conn.Line.X1 = r1; 
      conn.Line.Y1 = t1 + (b1 - t1)/2; 
      conn.Line.X2 = l2; 
      conn.Line.Y2 = t2 + (b2 - t2)/2; 

      conn.Line.Visibility = Visibility.Visible; 
     } 
     else if (r2 < l1) 
     { 
      conn.Line.X1 = r2; 
      conn.Line.Y1 = t2 + (b2 - t2)/2; 
      conn.Line.X2 = l1; 
      conn.Line.Y2 = t1 + (b1 - t1)/2; 

      conn.Line.Visibility = Visibility.Visible; 
     } 
     else if (b1 < t2) 
     { 
      conn.Line.X1 = l1 + (r1 - l1)/2; 
      conn.Line.Y1 = b1; 
      conn.Line.X2 = l2 + (r2 - l2)/2; 
      conn.Line.Y2 = t2; 

      conn.Line.Visibility = Visibility.Visible; 
     } 
     else if (b2 < t1) 
     { 
      conn.Line.X1 = l1 + (r1 - l1)/2; 
      conn.Line.Y1 = t1; 
      conn.Line.X2 = l2 + (r2 - l2)/2; 
      conn.Line.Y2 = b2; 

      conn.Line.Visibility = Visibility.Visible; 
     } 
     else 
     { 
      conn.Line.Visibility = System.Windows.Visibility.Collapsed; 
     } 
    } 

你打电话,每当一个箱子被移到RefreshLinesPositions:

private void Box_MouseMove(object sender, MouseEventArgs e) 
{ 
    if (draggedBox != null) 
    { 
     ... 

     RefreshLinesPositions(); 
    } 
} 

编辑:为节点

RefreshLinesPosition版本:

private void RefreshLinesPositions() 
{ 
    foreach (Connection conn in connections) 
    { 
     Point p1 = conn.Box1.TranslatePoint(new Point(0, 0), panel); 
     Point p2 = conn.Box2.TranslatePoint(new Point(0, 0), panel); 

     double t1 = p1.Y; 
     double b1 = p1.Y + conn.Box1.ActualHeight; 
     double l1 = p1.X; 
     double r1 = p1.X + conn.Box1.ActualWidth; 

     double t2 = p2.Y; 
     double b2 = p2.Y + conn.Box2.ActualHeight; 
     double l2 = p2.X; 
     double r2 = p2.X + conn.Box2.ActualWidth; 

     if (r1 < l2) 
     { 
      conn.Line.X1 = r1; 
      conn.Line.Y1 = t1 + (b1 - t1)/2; 
      conn.Line.X2 = l2; 
      conn.Line.Y2 = t2 + (b2 - t2)/2; 

      conn.Line.Visibility = Visibility.Visible; 

      conn.Node1.Text.RenderTransform = new TranslateTransform(r1, t1 + (b1 - t1)/2); 
      conn.Node2.Text.RenderTransform = new TranslateTransform(l2 - conn.Node2.Text.ActualWidth, t2 + (b2 - t2)/2); 
     } 
     else if (r2 < l1) 
     { 
      conn.Line.X1 = l1; 
      conn.Line.Y1 = t1 + (b1 - t1)/2; 
      conn.Line.X2 = r2; 
      conn.Line.Y2 = t2 + (b2 - t2)/2; 

      conn.Line.Visibility = Visibility.Visible; 

      conn.Node1.Text.RenderTransform = new TranslateTransform(l1 - conn.Node1.Text.ActualWidth, t1 + (b1 - t1)/2); 
      conn.Node2.Text.RenderTransform = new TranslateTransform(r2, t2 + (b2 - t2)/2); 
     } 
     else if (b1 < t2) 
     { 
      conn.Line.X1 = l1 + (r1 - l1)/2; 
      conn.Line.Y1 = b1; 
      conn.Line.X2 = l2 + (r2 - l2)/2; 
      conn.Line.Y2 = t2; 

      conn.Line.Visibility = Visibility.Visible; 

      conn.Node1.Text.RenderTransform = new TranslateTransform(l1 + (r1 - l1)/2, b1); 
      conn.Node2.Text.RenderTransform = new TranslateTransform(l2 + (r2 - l2)/2, t2 - conn.Node2.Text.ActualHeight); 
     } 
     else if (b2 < t1) 
     { 
      conn.Line.X1 = l1 + (r1 - l1)/2; 
      conn.Line.Y1 = t1; 
      conn.Line.X2 = l2 + (r2 - l2)/2; 
      conn.Line.Y2 = b2; 

      conn.Line.Visibility = Visibility.Visible; 

      conn.Node1.Text.RenderTransform = new TranslateTransform(l1 + (r1 - l1)/2, t1 - conn.Node1.Text.ActualHeight); 
      conn.Node2.Text.RenderTransform = new TranslateTransform(l2 + (r2 - l2)/2, b2); 
     } 
     else 
     { 
      conn.Line.Visibility = System.Windows.Visibility.Collapsed; 
     } 
    } 
} 

新的事件处理程序:

private void Button_Click_2(object sender, RoutedEventArgs e) 
{ 
    MyBox box1 = boxes.Single(b => b.Header == From); 
    MyBox box2 = boxes.Single(b => b.Header == To); 

    Connection conn = new Connection 
    { 
     Box1 = box1, 
     Box2 = box2, 
     Line = new Line { StrokeThickness = 1, Stroke = Brushes.Black }, 
     Node1 = new Node { Text = new TextBox() }, 
     Node2 = new Node { Text = new TextBox() } 
    }; 
    connections.Add(conn); 

    panel.Children.Add(conn.Line); 

    panel.Children.Add(conn.Node1.Text); 
    panel.Children.Add(conn.Node2.Text); 

    RefreshLinesPositions(); 
} 

我用这个来表示节点:

public partial class Node 
{ 
    public string Title { get; set; } 
    public TextBox Text { get; set; } 
} 
+0

我收到“From”和“To”的错误,表示它不存在 – terrorista

+0

它们只是两个字符串属性,我更新了代码。 – Pragmateek

+0

我点击连接,但什么也没有发生,也许我做错了什么 – terrorista

0
  1. 你必须得到每个盒子的位置;
  2. 在箱子之间画一个Path;
  3. 重绘上盒拖/放...
有两个 Rectangle

简单的例子:

XAML:

<Canvas x:Name="Root"> 
    <Rectangle 
     x:Name="rect1" 
     Fill="Aqua" 
     Width="20" 
     Height="20" 
     Canvas.Left="24" 
     Canvas.Top="44" /> 
    <Rectangle 
     x:Name="rect2" 
     Fill="Red" 
     Width="20" 
     Height="20" 
     Canvas.Left="119" 
     Canvas.Top="73" /> 
</Canvas> 

C#:

ConnectBoxes(Root, rect1, rect2); 
.... 

public void ConnectBoxes(Canvas container, Rectangle boxeSrc, Rectangle boxeDest) 
{ 
    var transform1 = boxeSrc.TransformToVisual(container); 
    var transform2 = boxeDest.TransformToVisual(container); 

    var lineGeometry = new LineGeometry() 
    { 
     StartPoint = transform1.Transform(
      new Point(boxeSrc.ActualWidth/2, boxeSrc.ActualHeight/2.0) 
     ), 
     EndPoint = transform2.Transform(
      new Point(boxeDest.ActualWidth/2.0, boxeDest.ActualHeight/2.0) 
     ) 
    }; 
    container.Children.Add(new Path() 
    { 
     Data = lineGeometry, 
     Fill = new SolidColorBrush(Colors.Brown), 
     Stroke = new SolidColorBrush(Colors.Brown), 

    }); 
} 
+0

这个例子是好的,但我怎么能做到这一点没有预制的对象呢?我猜想更好的方法来做这些行是通过点击一个按钮,允许从一个对象到另一个画一条线...... 这个链接上的例子是完美的,但它是在WPF,我不能把这在我的项目上:/ http://denisvuyka.wordpress。com/2007/10/13/wpf-draggable-objects-and-simple-shape-connectors/ – terrorista

+0

您是否知道如何在拖动时使矩形调整路径? – terrorista