/// <summary> /// Override for <seealso cref="UIElement.ArrangeCore" /> /// </summary> /// <remarks> /// We need information from AdornerInfo. Since we keep one AdornerInfo per /// Adorner, and we expect a 1:1 mapping between Adorners and our visual children, /// it makes more sense for us to iterate across AdornerInfos instead of /// our visual children here. This means that if someone somehow adds a non-Adorner /// child to AdornerLayer, it will never render. /// </remarks> /// <param name="finalSize">The location reserved for this element by the parent</param> protected override Size ArrangeOverride(Size finalSize) { // Not using an enumerator because the list can be modified during the loop when we call out. DictionaryEntry[] zOrderMapEntries = new DictionaryEntry[_zOrderMap.Count]; _zOrderMap.CopyTo(zOrderMapEntries, 0); for (int i = 0; i < zOrderMapEntries.Length; i++) { ArrayList adornerInfos = (ArrayList)zOrderMapEntries[i].Value; Debug.Assert(adornerInfos != null, "No adorners found for element in AdornerLayer._zOrderMap"); int j = 0; while (j < adornerInfos.Count) { AdornerInfo adornerInfo = (AdornerInfo)adornerInfos[j++]; if (!adornerInfo.Adorner.IsArrangeValid) // optimization { // We're dependent on Arrange to get the rendersize of the adorner, so Arrange before // doing our transform magic. adornerInfo.Adorner.Arrange(new Rect(new Point(), adornerInfo.Adorner.DesiredSize)); GeneralTransform proposedTransform = adornerInfo.Adorner.GetDesiredTransform(adornerInfo.Transform); GeneralTransform adornerTransform = GetProposedTransform(adornerInfo.Adorner, proposedTransform); int index = _children.IndexOf(adornerInfo.Adorner); if (index >= 0) { // Get the matrix transform out, skip all non affine transforms Transform transform = (adornerTransform != null) ? adornerTransform.AffineTransform : null; ((Adorner)(_children[index])).AdornerTransform = transform; } } if (adornerInfo.Adorner.IsClipEnabled) { adornerInfo.Adorner.AdornerClip = adornerInfo.Clip; } else if (adornerInfo.Adorner.AdornerClip != null) { adornerInfo.Adorner.AdornerClip = null; } } } return finalSize; }
/// <summary> /// AdornerLayer always returns a size of (0,0). /// The AdornerLayer's size should be the same as its parent, but not take up layout space. This means /// parents containing an AdornerLayer should stretch it to their own size. /// </summary> /// <param name="constraint"> /// Sizing constraint. /// </param> protected override Size MeasureOverride(Size constraint) { // Not using an enumerator because the list can be modified during the loop when we call out. DictionaryEntry[] zOrderMapEntries = new DictionaryEntry[_zOrderMap.Count]; _zOrderMap.CopyTo(zOrderMapEntries, 0); for (int i = 0; i < zOrderMapEntries.Length; i++) { ArrayList adornerInfos = (ArrayList)zOrderMapEntries[i].Value; Debug.Assert(adornerInfos != null, "No adorners found for element in AdornerLayer._zOrderMap"); int j = 0; while (j < adornerInfos.Count) { AdornerInfo adornerInfo = (AdornerInfo)adornerInfos[j++]; adornerInfo.Adorner.Measure(constraint); } } // Returning 0,0 prevents an invalidation of Measure for AdornerLayer from unnecessarily dirtying the parent. return new Size(); }