WPF和Adorners

时间:2016-07-20 20:37:48

标签: c# wpf adorner

WPF用户和开发人员。

我是WPF的新手,我实际上对装饰者有点困惑。到目前为止,我了解Adorner是在特定图层(AdornerLayer)中的元素顶部渲染的,该图层在可视树的更高级别中定义。

首先

如何为特定元素创建AdornerLayer,例如形状。

其次

我想我需要将AdornerLayer添加到Adorned元素的可视子元素中,以便在AdornerLayer中对Adorners进行有效的命中测试。怎么做?

提前谢谢你。

1 个答案:

答案 0 :(得分:1)

首先,你需要创建一个派生自Adorner的类,如下所示。您可以使用拇指或拇指进行渲染。这里是我之前实现过的代码,但为了简单起见我稍微改了一些,所以可能会有错误。

public class ResizingAdorner : Adorner
{
    Thumb topLeft;

    // To store and manage the adorner's visual children.
    VisualCollection visualChildren;

    // Initialize the ResizingAdorner.
    public ResizingAdorner(UIElement adornedElement)
        : base(adornedElement)
    {
        visualChildren = new VisualCollection(this);
        // Call a helper method to initialize the Thumbs
        BuildAdornerCorner(ref topLeft, Cursors.SizeNWSE);

        //these are events for the thumbs you may want it or not according to your needs//
        topLeft.PreviewMouseLeftButtonDown += new MouseButtonEventHandler(topLeft_PreviewMouseLeftButtonDown);
        topLeft.DragDelta += new DragDeltaEventHandler(HandleTopLeft);
    }
    //override this method for rendering
    protected override void OnRender(DrawingContext drawingContext)
    {
        Rect adornedElementRect = new Rect(this.AdornedElement.DesiredSize);
        // Some arbitrary drawing implements.
        SolidColorBrush RectBrush = new SolidColorBrush(Colors.Green);
        RectBrush.Opacity = 0.3;
        Pen renderPen = new Pen(RectBrush, 1.5);
        // Draw Rectangle
        drawingContext.DrawRectangle(null, renderPen, adornedElementRect);
    }

    // Arrange the Adorners.
    protected override Size ArrangeOverride(Size finalSize)
    {
        Rect adornedElementRect = new Rect(this.AdornedElement.DesiredSize);
        // desiredWidth and desiredHeight are the width and height of the element that's being adorned.  
        // These will be used to place the ResizingAdorner at the corners of the adorned element.  
        double desiredWidth = adornedElementRect.BottomRight.X;
        double desiredHeight = adornedElementRect.BottomRight.Y;
        // adornerWidth & adornerHeight are used for placement as well.
        double adornerWidth = adornedElementRect.TopLeft.X;
        double adornerHeight = adornedElementRect.TopLeft.Y;
        //Arrange PathPoints with the helper Methods
        topLeft.Arrange(new Rect(new Point(adornerWidth, adornerHeight), new Point(desiredWidth, desiredHeight)));
        // Return the final size.
        return finalSize;
    }
    // set some appearance properties, and add the elements to the visual tree//
    void BuildAdornerCorner(ref Thumb cornerThumb, Cursor customizedCursor)
    {
        Path adornered = AdornedElement as Path;
        if (cornerThumb != null) return;
        cornerThumb = new Thumb();
        // Set some arbitrary visual characteristics.
        cornerThumb.Cursor = customizedCursor;
        cornerThumb.Height = cornerThumb.Width = 10;
        cornerThumb.Opacity = 1;
        cornerThumb.Background = new SolidColorBrush(Colors.Black);

        visualChildren.Add(cornerThumb);
    }

    // UnScale Adorners. this part is optional
    public override GeneralTransform GetDesiredTransform(GeneralTransform transform)
    {
        if (this.visualChildren != null)
        {
            foreach (var thumb in this.visualChildren.OfType<Thumb>())
            {
                thumb.RenderTransform
                    = new ScaleTransform(1 / ScaleXC, 1 / ScaleYC);
                thumb.RenderTransformOrigin = new Point(0.5, 0.5);
            }
        }
        return base.GetDesiredTransform(transform);
    }
}

之后使用此类如下所示来装饰元素

    AdornerLayer ADL;  //consider this is as a public field somewhere in your class 
    ...
    ...
    ResizingAdorner A = new XamlEditor.ResizingAdorner(p); // p is an UIElement I my case
    ADL = AdornerLayer.GetAdornerLayer(p);
    ADL.Add(A);