问题
So If I have a binding placed on width of a child object that links it to its parent's ActualWidth
, what will happen?
My guess is that the parent measures how much width the child wants, the child tells the parent 0 width, then the parent is given actual space during arrange, and it attempts to give the child zero since the child didn't want any. Then the actual width of the space given to the parent should cause the binding to change the child's width. At this point I would guess layout is performed again.
However, this assumes that the binding doesn't propagate that fast. I'm still hazy on when the bound value propagates to the target. It all depends on when the parent's actualwidth value changes. Does this occur after layout finishes? and then the bound pieces update? Does every binding interrupt the currently running code to go update the target value? if not, wouldn't it cause problems if one binding propagates a change that requires a redraw, then another binding propagates a different change that causes redraw, etc.
Some people asked what my actual problem was:
So originally I wanted to have a control stretch to fill the available space. Simple enough, but I wanted to have it be in a scrollviewer. Scrollviewer gives infinite space to its children during measure. So instead you can bind the width and height of the child control to the parent's actualwidth and actual height; layout does a second pass, and all seems swell.
However, later I was having issues of a similar kind stretching a control in a controltemplate but then found out that I can set a minwidth and alignment=stretch to have it stretch.
However, I distinctly remembered trying that earlier on my other control and having it not work, so I went back and tried to figure out what the difference between the two cases was. Basically it boiled down to one of them being in a stackpanel a few levels up.
So now I am using a binding for one and the minwidth plus alignment method for the other. Anyway was only interested in this to make sure that the way i'm doing things doesn't create weird bugs later.
I am hoping that layout doesn't run immediately when a width or height is changed but instead the system rechecks for size changes periodically
回答1:
According to the DispatherPriority enum, DataBinding
occurs before Rendering
.
- Send
- Normal - Constructors run here
- DataBind
- Render
- Loaded
- Background
- ContextIdle
- ApplicationIdle
- SystemIdle
- Inactive
- Invalid
- Input
So the binding would try to evaluate first before the render occurs.
However rendering can cause your binding to update, so if the process of rendering the parent panel would increase the width of the panel (for example, a parent panel placed inside of another panel that automatically stretches its children to take up 100% of the space like a Grid
or last element in a DockPanel
), then it will trigger an update on the binding and increase the width of the child during the render cycle.
The 2nd part of this SO answer may also help you understand. Take note of #6 too.
Sequence of events when a Window is created and shown
As requested, here is the sequence of major events in WPF when a window is created and shown:
Constructors and getters/setters are called as objects are created, including PropertyChangedCallback, ValidationCallback, etc on the objects being updated and any objects that inherit from them
As each element gets added to a visual or logical tree its Intialized event is fired, which causes Styles and Triggers to be found applied in addition to any element-specific initialization you may define [note: Initialized event not fired for leaves in a logical tree if there is no PresentationSource (eg Window) at its root]
The window and all non-collapsed Visuals on it are Measured, which causes an ApplyTemplate at each Control, which causes additional object tree construction including more constructors and getters/setters
The window and all non-collapsed Visuals on it are Arranged
The window and its descendants (both logical and visual) receive a Loaded event
Any data bindings that failed when they were first set are retried
The window and its descendants are given an opportunity to render their content visually
Steps 1-2 are done when the Window is created, whether or not it is shown. The other steps generally don't happen until a Window is shown, but they can happen earlier if triggered manually.
来源:https://stackoverflow.com/questions/17604072/wpf-what-happens-when-a-childs-width-is-bound-to-a-parents-actualwidth