Sco*_*oby 19 wpf grid connector lines wpf-controls
我正在网格上创建控件(比如按钮).我想在控件之间创建一个连接线.假设你在一个按钮上做了mousedown并将鼠标放在另一个按钮上.这应该在这两个按钮之间画一条线.
有人可以帮助我或给我一些关于如何做到这一点的想法吗?
提前致谢!
Rob*_*ser 44
我正在做类似的事; 这是我所做的快速总结:
为了处理控件之间的拖放,Web上有相当多的文献(只是搜索WPF拖放).默认的拖放实现过于复杂,IMO,我们最终使用一些附加的DP来使其更容易(类似于这些).基本上,你想要一个看起来像这样的拖拽方法:
private void onMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
UIElement element = sender as UIElement;
if (element == null)
return;
DragDrop.DoDragDrop(element, new DataObject(this), DragDropEffects.Move);
}
Run Code Online (Sandbox Code Playgroud)
在目标上,将AllowDrop设置为true,然后向Drop添加一个事件:
private void onDrop(object sender, DragEventArgs args)
{
FrameworkElement elem = sender as FrameworkElement;
if (null == elem)
return;
IDataObject data = args.Data;
if (!data.GetDataPresent(typeof(GraphNode))
return;
GraphNode node = data.GetData(typeof(GraphNode)) as GraphNode;
if(null == node)
return;
// ----- Actually do your stuff here -----
}
Run Code Online (Sandbox Code Playgroud)
现在是棘手的部分!每个控件都公开一个AnchorPoint DependencyProperty.当引发LayoutUpdated事件时(即控件移动/调整大小/等),控件将重新计算其AnchorPoint.添加连接线时,它会绑定源和目标的AnchorPoints的DependencyProperties.[ 编辑:正如Ray Burns在评论中指出的那样,Canvas和网格只需要在同一个地方; 它们不需要在同一层次结构中(尽管它们可能是)]
要更新位置DP:
private void onLayoutUpdated(object sender, EventArgs e)
{
Size size = RenderSize;
Point ofs = new Point(size.Width / 2, isInput ? 0 : size.Height);
AnchorPoint = TransformToVisual(node.canvas).Transform(ofs);
}
Run Code Online (Sandbox Code Playgroud)
用于创建行类(也可以在XAML中完成):
public sealed class GraphEdge : UserControl
{
public static readonly DependencyProperty SourceProperty = DependencyProperty.Register("Source", typeof(Point), typeof(GraphEdge), new FrameworkPropertyMetadata(default(Point)));
public Point Source { get { return (Point) this.GetValue(SourceProperty); } set { this.SetValue(SourceProperty, value); } }
public static readonly DependencyProperty DestinationProperty = DependencyProperty.Register("Destination", typeof(Point), typeof(GraphEdge), new FrameworkPropertyMetadata(default(Point)));
public Point Destination { get { return (Point) this.GetValue(DestinationProperty); } set { this.SetValue(DestinationProperty, value); } }
public GraphEdge()
{
LineSegment segment = new LineSegment(default(Point), true);
PathFigure figure = new PathFigure(default(Point), new[] { segment }, false);
PathGeometry geometry = new PathGeometry(new[] { figure });
BindingBase sourceBinding = new Binding {Source = this, Path = new PropertyPath(SourceProperty)};
BindingBase destinationBinding = new Binding { Source = this, Path = new PropertyPath(DestinationProperty) };
BindingOperations.SetBinding(figure, PathFigure.StartPointProperty, sourceBinding);
BindingOperations.SetBinding(segment, LineSegment.PointProperty, destinationBinding);
Content = new Path
{
Data = geometry,
StrokeThickness = 5,
Stroke = Brushes.White,
MinWidth = 1,
MinHeight = 1
};
}
}
Run Code Online (Sandbox Code Playgroud)
如果你想获得更多的爱好者,你可以在源和目标上使用MultiValueBinding并添加一个创建PathGeometry的转换器.这是GraphSharp的一个例子.使用此方法,您可以在线的末尾添加箭头,使用贝塞尔曲线使其看起来更自然,将线路绕过其他控件(尽管这可能比听起来更难)等等.