WPF: how to bind lines to UI elements?
I use this method to bind a Line to the center of two ScatterViewItems:
private void BindLineToScatterViewItems(Shape line, ScatterViewItem origin, ScatterViewItem destination)
{
// Bind line.(X1,Y1) to origin.ActualCenter
BindingOperations.SetBinding(line, Line.X1Property, new Binding { Source 开发者_如何学编程= origin, Path = new PropertyPath("ActualCenter.X") });
BindingOperations.SetBinding(line, Line.Y1Property, new Binding { Source = origin, Path = new PropertyPath("ActualCenter.Y") });
// Bind line.(X2,Y2) to destination.ActualCenter
BindingOperations.SetBinding(line, Line.X2Property, new Binding { Source = destination, Path = new PropertyPath("ActualCenter.X") });
BindingOperations.SetBinding(line, Line.Y2Property, new Binding { Source = destination, Path = new PropertyPath("ActualCenter.Y") });
}
But now I'd like to bind it from the bottom from one ScatterViewItem to the top of the another ScatterViewItem:
How can I achieve that?
You could:
Use a
IValueConverter
that takes the bounding rectangle of the view item and a converter parameter to specify the side to calculate the center from.public enum MidpointSide { None, Left, Top, Right, Bottom } public class MidpointConverter : IValueConverter { private bool returnY; public MidpointConverter(bool returnY) { this.returnY = returnY; } public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { var scatter = value as ScatterViewItem; var side = (MidpointSide)parameter; var center = scatter.ActualCenter; var halfW = scatter.ActualWidth / 2.0; var halfH = scatter.ActualHeight / 2.0; Point point = null; switch (side) { case MidpointSide.Left: point = new Point(center.X - halfW, center.Y); break; case MidpointSide.Top: point = new Point(center.X, center.Y - halfH); break; case MidpointSide.Right: point = new Point(center.X + halfW, center.Y); break; case MidpointSide.Bottom: point = new Point(center.X, center.Y + halfH); break; default: return null; } return this.returnY ? point.Y : point.X; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } }
The converter you would use would be:
var x = new MidpointConverter(false), y = MidpointConverter(true); BindingOperations.SetBinding(line, Line.X1Property, new Binding { Source = origin, Converter = x, ConverterParameter = MidpointSide.Bottom }); BindingOperations.SetBinding(line, Line.Y1Property, new Binding { Source = origin, Converter = y, ConverterParameter = MidpointSide.Bottom }); // Definitely more heavyweight than just changing the `ZIndex` // You run into the problem that you can't bind the 'start' and 'end' // of a line, only X1/Y1 and X2/Y2 making this converter involved
Keep the same
ActualCenter
bindings, but make theZIndex
of the line below that of the rectangles. Using this approach will likely keep you from having to detect if oneScatterViewItem
moves in such a way that needs to change the side used in the converter.
BindingOperations.SetBinding(line, Line.X1Property, new Binding { Source = origin, Path = new PropertyPath("ActualCenter.X"),Converter=converter });
is there a reason this wouldnt work to set the converter?
精彩评论