我有一个非常简单的 WPF 应用程序,可以在画布中呈现简单的形状:
蓝色方块是ItemsControl
红色圆圈是Controls
我的应用程序中的以下步骤是在形状之间添加连接线。形状将被移动,我希望自动移动连接。我读到了如何添加连接绑定。
与画布直接子(容器)一起工作正常,但如果我想连接节点,它就不起作用。看来如果我不Canvas.SetLeft()
打电话Canvas.SetTop()
明确地Canvas.GetLeft()
,然后Canvas.GetTop()
返回 NAN。
我应该如何进行?
- 我是否应该实现一种机制来让所有对象都放在我的画布中,这样我总是可以计算
Canvas.GetLeft()
? - 我应该以其他方式进行吗?
源代码和截图
这是示例的源代码。你可以在这里找到完整的例子:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Container container1 = new Container() { Width = 100, Height = 100 };
Node node1 = new Node() { Width = 50, Height = 50 };
container1.Items.Add(node1);
Container container2 = new Container() { Width = 100, Height = 100 };
Node node2 = new Node() { Width = 50, Height = 50 };
container2.Items.Add(node2);
Canvas.SetLeft(container2, 200);
myCanvas.Children.Add(container1);
myCanvas.Children.Add(container2);
}
}
class Container : ItemsControl
{
protected override void OnRender(DrawingContext drawingContext)
{
drawingContext.DrawRectangle(
Brushes.Blue, null, new Rect(0, 0, this.Width, this.Height));
}
}
class Node : Control
{
protected override void OnRender(DrawingContext drawingContext)
{
drawingContext.DrawEllipse(
Brushes.Red, null,
new Point(Width / 2, Height / 2), Width / 2, Height / 2);
}
}
这就是我实现形状之间连接的方式:
public Shape AddConnection(UIElement source, UIElement target)
{
Connector conn = new Connector();
conn.SetBinding(Connector.StartPointProperty,
CreateConnectorBinding(source));
conn.SetBinding(Connector.EndPointProperty,
CreateConnectorBinding(target));
return conn;
}
private MultiBinding CreateConnectorBinding(UIElement connectable)
{
// Create a multibinding collection and assign an appropriate converter to it
MultiBinding multiBinding = new MultiBinding();
multiBinding.Converter = new ConnectorBindingConverter();
// Create binging #1 to IConnectable to handle Left
Binding binding = new Binding();
binding.Source = connectable;
binding.Path = new PropertyPath(Canvas.LeftProperty);
multiBinding.Bindings.Add(binding);
// Create binging #2 to IConnectable to handle Top
binding = new Binding();
binding.Source = connectable;
binding.Path = new PropertyPath(Canvas.TopProperty);
multiBinding.Bindings.Add(binding);
// Create binging #3 to IConnectable to handle ActualWidth
binding = new Binding();
binding.Source = connectable;
binding.Path = new PropertyPath(FrameworkElement.ActualWidthProperty);
multiBinding.Bindings.Add(binding);
// Create binging #4 to IConnectable to handle ActualHeight
binding = new Binding();
binding.Source = connectable;
binding.Path = new PropertyPath(FrameworkElement.ActualHeightProperty);
multiBinding.Bindings.Add(binding);
return multiBinding;
}
Connector
对象非常简单。它有一个 LineGeometry 并公开两个 DependencyProperties 来计算起点和终点。
public static readonly DependencyProperty StartPointProperty =
DependencyProperty.Register(
"StartPoint",
typeof(Point),
typeof(Connector),
new FrameworkPropertyMetadata(
new Point(0, 0),
FrameworkPropertyMetadataOptions.AffectsMeasure));
public static readonly DependencyProperty EndPointProperty =
DependencyProperty.Register(
"EndPoint",
typeof(Point),
typeof(Connector),
new FrameworkPropertyMetadata(
new Point(0, 0),
FrameworkPropertyMetadataOptions.AffectsMeasure));