anon
anon

Reputation:

Use Binding to connect Ellipses with a Line

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

Answers (2)

decyclone
decyclone

Reputation: 30830

You can use IValueConverter to change/transform values while Binding.

Here is something I cooked up:

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);

Converter:

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

ColinE
ColinE

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

Related Questions