【问题标题】:WPF and AdornersWPF 和装饰器
【发布时间】:2016-11-24 05:32:15
【问题描述】:

您好 WPF 用户和开发人员。

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

首先

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

其次

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

提前谢谢你。

【问题讨论】:

    标签: c# wpf adorner


    【解决方案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);
    

    【讨论】:

    • 非常感谢您提供的详细示例,到目前为止,我在全球范围内了解您在做什么,但我面临的问题是,当没有 AdornerLayer 时(在您的情况下,您认为有一个),我怎么能创造它。以及如何从包含装饰元素的画布中检测对装饰器的点击。
    • 我不确定我是否正确理解了您的问题,但是,假设您在画布中有 Shape(据我所知也是 UIElement),您可以挂钩该形状的 mouseleftbuttondown 事件以添加装饰器(我回答的第二部分)。对于命中测试,您可以挂钩视觉元素的事件(在我的情况下,我挂钩拇指的事件),
    • 在我的情况下,当我调用 AdornerLayer.GetAdornerLayer 函数时,带有画布的窗口没有装饰层。如何在 UiElement 上方创建图层???
    猜你喜欢
    • 2015-03-04
    • 2013-02-06
    • 2010-11-25
    • 2010-11-24
    • 1970-01-01
    • 1970-01-01
    • 2011-03-14
    • 2010-10-04
    • 1970-01-01
    相关资源
    最近更新 更多