Reputation:
I use the following Bindings to connect two Ellipses with a line:
Line l = new Line();
l.Stroke = Brushes.Green;
l.StrokeThickness = 3;
Binding x1 = new Binding(); x1.Path = new PropertyPath(Canvas.LeftProperty);
Binding y1 = new Binding(); y1.Path = new PropertyPath(Canvas.TopProperty);
Binding x2 = new Binding(); x2.Path = new PropertyPath(Canvas.LeftProperty);
Binding y2 = new Binding(); y2.Path = new PropertyPath(Canvas.TopProperty);
x1.Source = y1.Source = e;
x2.Source = y2.Source = e1;
l.SetBinding(Line.X1Property, x1);
l.SetBinding(Line.Y1Property, y1);
l.SetBinding(Line.X2Property, x2);
l.SetBinding(Line.Y2Property, y2);
Dependencies.Children.Add(l);
This works great, but the problem is, the lines are drawn on the left top of the Ellipse. I'd like to use the center of the Ellipse. Therefore I would have to add Ellipse#width / 2 to the x property. But how can I do that?
Upvotes: 3
Views: 1094
Reputation: 30830
You can use IValueConverter
to change/transform values while Binding
.
Canvas Dependencies = new Canvas();
Ellipse e1 = new Ellipse() { Width = 200, Height = 200, Stroke = Brushes.Red, StrokeThickness = 1 };
Ellipse e2 = new Ellipse() { Width = 200, Height = 200, Stroke = Brushes.Red, StrokeThickness = 1 };
Line l = new Line();
l.Stroke = Brushes.Green;
l.StrokeThickness = 3;
Binding x1 = new Binding(); x1.Path = new PropertyPath(Canvas.LeftProperty); x1.Converter = new MyConverter(); x1.ConverterParameter = e1;
Binding y1 = new Binding(); y1.Path = new PropertyPath(Canvas.TopProperty); y1.Converter = new MyConverter(); y1.ConverterParameter = e1;
Binding x2 = new Binding(); x2.Path = new PropertyPath(Canvas.LeftProperty); x2.Converter = new MyConverter(); x2.ConverterParameter = e2;
Binding y2 = new Binding(); y2.Path = new PropertyPath(Canvas.TopProperty); y2.Converter = new MyConverter(); y2.ConverterParameter = e2;
x1.Source = y1.Source = e1;
x2.Source = y2.Source = e2;
l.SetBinding(Line.X1Property, x1);
l.SetBinding(Line.Y1Property, y1);
l.SetBinding(Line.X2Property, x2);
l.SetBinding(Line.Y2Property, y2);
Dependencies.Children.Add(e1);
Dependencies.Children.Add(e2);
Dependencies.Children.Add(l);
SizeChangedEventHandler act = (Object s, SizeChangedEventArgs args) =>
{
BindingOperations.GetBindingExpressionBase(l, Line.X1Property).UpdateTarget();
BindingOperations.GetBindingExpressionBase(l, Line.Y1Property).UpdateTarget();
BindingOperations.GetBindingExpressionBase(l, Line.X2Property).UpdateTarget();
BindingOperations.GetBindingExpressionBase(l, Line.Y2Property).UpdateTarget();
};
e1.SizeChanged += act;
e2.SizeChanged += act;
Canvas.SetLeft(e1, 200);
Canvas.SetTop(e1, 200);
Canvas.SetLeft(e2, 500);
Canvas.SetTop(e2, 500);
Grid2.Children.Add(Dependencies);
public class MyConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
Ellipse e = parameter as Ellipse;
Double d = (Double)value;
return d + (e.ActualWidth / 2);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
Ellipse e = parameter as Ellipse;
Double d = (Double)value;
return d - (e.ActualWidth / 2);
}
}
Note that the converter considers Ellipse.Width only. You will need to modify it to make it work correctly.
Upvotes: 2
Reputation: 70122
Your binding now depends on two properties, the Canvas.Left (or Canvas.Top), and the Ellipse.ActualWidth (or height). To achieve this you can use a multibinding. See the following examples:
http://www.switchonthecode.com/tutorials/wpf-tutorial-using-multibindings
However, there are other, possibly simpler alternatives. You could use a render transform to translate your ellipses by an X position which is half of its width and a Y position that is half of its height, to centre your ellipse at the position given by Canvas.Left and canvas.Top
Regards, Colin E.
Upvotes: 1