I’m playing with a basic training device as an intro to WPF, where the user is presented with a column of items on the left of the screen, and one on the right. Their task is to draw lines connecting related items on the left to items on the right. I have started with a very simple 3 column Grid with Rectangles down the left and right columns, with nothing in the centre column, and a simple static Line between two rectangles (I don’t think I did too bad for a first attempt, without Google), but when I try and set the line to Stretch, it starts in the top left corner of the canvas, not on the locus of the Origin. Without stretch it is correctly positioned, but remains static during grid resizing. Here is my attempt:
private Line _line;
private void DrawLink(int row1, int col1, int row2, int col2)
{
// Find the locus of the Origin rectangle.
var orig = (Rectangle)grid.Children[row1 * ColumnCount + col1];
var x1 = orig.ActualWidth - orig.ActualHeight / 2 / 2;
var y1 = orig.ActualHeight / 2;
var gp1 = orig.TranslatePoint(new Point(x1, y1), grid);
// Find the locus of the Target rectangle.
var targ = (Rectangle)grid.Children[row2 * ColumnCount + col2];
var x2 = targ.ActualHeight / 2 / 2;
var y2 = targ.ActualHeight / 2;
var gp2 = targ.TranslatePoint(new Point(x2, y2), grid);
_line = new Line
{
Stroke = new SolidColorBrush(Colors.Red),
StrokeThickness = 2,
// Think this isn't working because line is added dynamically.
Stretch = Stretch.Fill,
X1 = gp1.X,
Y1 = gp1.Y,
X2 = gp2.X,
Y2 = gp2.Y
};
gridCanvas.Children.Add(_line);
}
If you choose
Stretch.Fillyou can only control whether the line is horizontal, vertical, diagonal falling, or diagonal rising, however you could position the end points differently, e.g. by using theMargin. To make the line resize with its container you need to choose a panel which transforms its children, aCanvasis not very suitable in this case, you might be able to use aGridinstead.Here is full example which illustrates the above points, note the
Marginsand the setting of eitherY1orY2on theLines:If the content resizes dynamically on the vertical axis as well you might need to approach it differently. For example you could then wrap the lines in a
ContentControlwhich starts at the respective lower row and only spans the rows it crosses, it would contain theLinewhich then has the same value for theTopandBottomparts of the Margin (half the height of one row). To get the proper value the Margin could be bound with a respective converter in place.