| File: MS\Internal\Controls\TemplatedAdorner.cs | Web Access |
| Project: src\wpf\src\Microsoft.DotNet.Wpf\src\PresentationFramework\PresentationFramework.csproj (PresentationFramework) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // Description: // TemplatedAdorner applies the style provided in the ctor to a // control and provides a transform via GetDesiredTransform that // will cause the AdornedElementPlaceholder to be positioned directly // over the AdornedElement. // // See specs at Specs/Validation.mht // using System.Windows.Media; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; namespace MS.Internal.Controls { /// <summary> /// This class is sealed because it calls OnVisualChildrenChanged virtual in the /// constructor and it does not override it, but derived classes could. /// </summary> internal sealed class TemplatedAdorner : Adorner { private Control _child; /// <summary> /// The clear the single child of a TemplatedAdorner /// </summary> public void ClearChild() { this.RemoveVisualChild(_child); _child = null; } public TemplatedAdorner(UIElement adornedElement, ControlTemplate adornerTemplate) : base(adornedElement) { Debug.Assert(adornedElement != null, "adornedElement should not be null"); Debug.Assert(adornerTemplate != null, "adornerTemplate should not be null"); Control control = new Control { DataContext = Validation.GetErrors(adornedElement), //control.IsEnabled = false; // Hittest should not work on visual subtree IsTabStop = false, // Tab should not get into adorner layer Template = adornerTemplate }; _child = control; this.AddVisualChild(_child); } /// <summary> /// Adorners don't always want to be transformed in the same way as the elements they /// adorn. Adorners which adorn points, such as resize handles, want to be translated /// and rotated but not scaled. Adorners adorning an object, like a marquee, may want /// all transforms. This method is called by AdornerLayer to allow the adorner to /// filter out the transforms it doesn't want and return a new transform with just the /// transforms it wants applied. An adorner can also add an additional translation /// transform at this time, allowing it to be positioned somewhere other than the upper /// left corner of its adorned element. /// </summary> /// <param name="transform">The transform applied to the object the adorner adorns</param> /// <returns>Transform to apply to the adorner</returns> public override GeneralTransform GetDesiredTransform(GeneralTransform transform) { if (ReferenceElement == null) return transform; GeneralTransformGroup group = new GeneralTransformGroup(); if(transform != null) { group.Children.Add(transform); } GeneralTransform t = this.TransformToDescendant(ReferenceElement); if (t != null) { group.Children.Add(t); } return group; } public FrameworkElement ReferenceElement { get { return _referenceElement; } set { _referenceElement = value; } } /// <summary> /// Derived class must implement to support Visual children. The method must return /// the child at the specified index. Index must be between 0 and GetVisualChildrenCount-1. /// /// By default a Visual does not have any children. /// /// Remark: /// During this virtual call it is not valid to modify the Visual tree. /// </summary> protected override Visual GetVisualChild(int index) { if (_child == null || index != 0) { throw new ArgumentOutOfRangeException(nameof(index), index, SR.Visual_ArgumentOutOfRange); } return _child; } /// <summary> /// Derived classes override this property to enable the Visual code to enumerate /// the Visual children. Derived classes need to return the number of children /// from this method. /// /// By default a Visual does not have any children. /// /// Remark: During this virtual method the Visual tree must not be modified. /// </summary> protected override int VisualChildrenCount { get { return _child != null ? 1 : 0; } } /// <summary> /// Measure adorner. /// </summary> protected override Size MeasureOverride(Size constraint) { Debug.Assert(_child != null, "_child should not be null"); if (ReferenceElement != null && AdornedElement != null && AdornedElement.IsMeasureValid && !DoubleUtil.AreClose(ReferenceElement.DesiredSize, AdornedElement.DesiredSize) ) { ReferenceElement.InvalidateMeasure(); } (_child).Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity)); return (_child).DesiredSize; } /// <summary> /// Default control arrangement is to only arrange /// the first visual child. No transforms will be applied. /// </summary> protected override Size ArrangeOverride(Size size) { Size finalSize; finalSize = base.ArrangeOverride(size); _child?.Arrange(new Rect(new Point(), finalSize)); return finalSize; } internal override bool NeedsUpdate(Size oldSize) { bool result = base.NeedsUpdate(oldSize); Visibility desired = AdornedElement.IsVisible ? Visibility.Visible : Visibility.Collapsed; if (desired != this.Visibility) { this.Visibility = desired; result = true; } return result; } private FrameworkElement _referenceElement; } }