tags:

views:

53

answers:

2

How can one be notified as to when a UIElement has been moved (eg: when a Panel has reArranged its child elements, or an Animation is moving them around)?

So far I've investigated the following dead ends: a) the LayoutUpdated event: works when the Panel moves things around -- but doesn't fire when Animations are applied to the position of a child event.

b) Binding: I've created a DP (called ProxyLeft) with a callback, and Bound it the value of the Canvas.Left DP of a child element.

This does work (in that all changes to the Canvas.Left of the child element, whether by end user or applied Animation, are picked up). But Binding to Canvas.Left is not 'hollistic enough': It would only work if the Panel is a Canvas, but is of no use if the Panel were a StackPanel (StackPanel's don't use Canvas.Left to determine position of element (the layout is updated when the panel size changes and/or prior siblings added or updated in size, etc.). I guess what I'm looking for is a Binding on the Rect of the child element...but that doesn't exists.

At present, i don't see a way of doing it, unless I am the creator of the Panel (CustomPanel) and can be involved with the layout mechanism and at that moment update an AttachedProperty of the child element (eg: CustomPanel.Rect) at that moment...and even that won't work -- as it won't be updated by animations applied to the child element.

Can one be notified when an element has moved? If so, how?

Thanks ever so much.

A: 

I think the simple answer to your question is: no.

You appear to want a very general system to determine if an element has moved. However such a requirement is actually quite alien to the layout system.

It would first require a definition of what "moved" really means. Movement must be relative to some fixed point, what would that fixed point be? Screen, Browser client window, Browser view port, Application Visual Root, some arbitary ancestor of the element, the direct parent of the element? Some means of tracking changes not just the elements position within a parent but also that parents position within its parent and so on may be needed.

The layout system seems to be quite hostile to any such concept of an element being actually anywhere specifically. The only place where there is any interest in where an element might be is where an Panel calls its Arrange method but even then the position is only relative to the Panel. This Arrange method is handled by the UIElement which exposes nothing of the position in its public interface.

AnthonyWJones
Hi Anythony: I'm trying to render a line (think Visio arrow/link) to a Target element in a Panel. One way to tackle that is to arrange both the targets and the lines between them. Ok...but not flexible.More flexible would be to just arrange the targets, and let them 'broadcast' their new location to the Lines, which would redraw themselves based on the received updated target Rect.Allong the lines of what was proposed here:http://silverlightfoundry.blogspot.com/2009/04/element-binding-that-acts-like-visio.html
Ciel
I agree that 'moved' is a nuanced subject... the original Rect relative to conatiner, its Translation...its Projection...Basically we're talking about being warned anytime the destination target's Rect, relative to an agreed upon Context (eg: parent Panel) is updated.The only solution that I think covers all these bases is:http://skysigal.xact-solutions.com/Blog/tabid/427/EntryId/1071/Silverlight-Detecting-changes-in-location-of-a-Panel-rsquo-s-Children.aspxBut it relies on some pretty expensive moves...hence my checking to see if anybody has a less expensive solution...
Ciel
I think you might need to review why you need a more flexiable solution. If you do then you will have to pay the price or take a look at different base technology to deliver the required UI.
AnthonyWJones
Thanks...But there is often a need for such an approach: there should be as often as possible a separation of concerns between the placement and animation, or placement and decorators/adorners. One example is separating the placement of a Panel (eg: FlowPanel) and the animation needed to 'flow' them as one resizes, etc. The Animation logic could be built in...but it would be limited to whatever the dev concocted up - or has to expose a ton of parameters. One should leave this Animation logic to a external modifier. Hence the need to be notified. Same for an Adorner. Or Line...no?
Ciel
ie... I'll pay the price until I find a cheaper solution :-)
Ciel
A: 

I'm thinking out loud here, so just ignore it if it is stupid, or if I misunderstood the scenario.

Give each target a dispatchertimer. Let this tick every 0.1 seconds or so when the user is dragging the element or an animation is playing. On each tick, broadcast the current position using some sort of global messenger class. You would need some sort of unique identifier for each target so that the Line objects can listen to the events from the messenger, determine whether it is "their" target object that has moved and, if so, redraw themselves accordingly. For my suggestion to work well I guess you would need to start/stop the dispatchertimer whenever the animation starts or stops. Otherwise you will probably end up with poor performance. How many objects are you anticipating will be on the screen at the same time?

Henrik Söderlund