Reputation: 4317
I need something to get the position of a sub-sub element relative to the container. TransformToAncestor does that. However, the element and subelements move, resize change, their layout, etc. I need a way to keep the position up-to-date. Like an event if anything happend that would affect my TransformToAncestor operation. Or an "AbsolutePosition" dependency property I can bind to.
Background:
I'm doing sort of a work flow editor. There are 'modules' that have one or more ports and lines that connect the modules from port to port.
The XAML stucture looks like this:
<Canvas>
<Module Left="..." Top="..." Width="..." Height="...">
<Grid><otherelement><somemorelayouting>
<Port Name="a" />
<Port Name="b" />
</somemorelayouting></otherelement></Grid>
</Module>
<Module Left="..." Top="..." Width="..." Height="...">
<differentsetoflayouts>
<Port Name="c" />
<Port Name="d" />
</differentsetoflayouts>
</Module>
<Line startpoint="{binding source=a, path=abs_position}" endpoint="{binding source=c, path=abs_position}" />
</Canvas>
The line connects port a of the first module with port b of the second. The end points should be at the top left corner of the port-element (for the moment). This "abs_position" property used in this example does unfurtunatly not exist (I'm using start/endpoint here instead of X1,X2,Y1,Y2 only to improve readability)
Upvotes: 3
Views: 4593
Reputation: 10039
I wrote an article on code project about data-binding to the position a UI element:
http://www.codeproject.com/Articles/139216/A-Simple-Technique-for-Data-binding-to-the-Positio
Your workflow editor also sounds like it might similar to my graphing and diagramming control called NetworkView:
http://www.codeproject.com/Articles/182683/NetworkView-A-WPF-custom-control-for-visualizing-a
Upvotes: 0
Reputation: 4317
I propose to use kek444's solution with a custom layout if possible. However should this not be applicable, here is another approch I found while googling kek444's hints.
The event UIElement.LayoutUpdated is fired whenever something on the layout changes. It reacts to movement, resize, add/remove of elements, and about anything anything else. It does not only fire if the element is affected on which the event is registered, but also if any other element using the same dispatch thread is touched. As a result it is fired very often, so using it might have quite some performance impact.
See also Dave Relyea's blog entry. Stackoverflow does not let me post two links, so just google for "Layout Events - SizeChanged and LayoutUpdated".
Upvotes: 4
Reputation: 14111
If you implement your container with attached dependency properties for location of children elements (like the Canvas panel does, which seems to be the case according to provided code), then you can bind to changes of that dependency property using a DependencyPropertyDescriptor.
DependencyPropertyDescriptor dpd = DependencyPropertyDescriptor.FromProperty(Canvas.TopProperty, typeof(Canvas));
dpd.AddValueChanged(canvas1, new EventHandler(topChangedCallback));
Upvotes: 2