用于自定义边框的 WPF 装饰器类作为矩形事件不起作用

问题描述 投票:0回答:1

我有一个装饰器类,我想在装饰器的孩子周围包裹一个“边框”。 边框有四个边,每个边都是一个 FrameworkElement。 后者可用于各种目的,例如调整大小、装饰等......子项,因此我想向用户公开侧面,因此侧面的 DependencyProperties ,我使用大多数自定义控件来执行此操作。 装饰器如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
using System.Windows.Shapes;

namespace CustomControlLibrary
{
    public class BorderWrapper : Decorator, INotifyPropertyChanged
    {
        #region DependencyProperties
        // Override base Properties
        // Summary:
        //     Sets the Size privately thus making the user unable to set the Size.
        public new double Width
        {
            get { return (double)GetValue(WidthProperty); }
            private set { SetValue(WidthProperty, value); }
        }

        public static readonly new DependencyProperty WidthProperty =
            DependencyProperty.Register("Width", typeof(double), typeof(BorderWrapper), new FrameworkPropertyMetadata(
                default(double), FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.AffectsMeasure));

        public new double Height
        {
            get { return (double)GetValue(HeightProperty); }
            private set { SetValue(HeightProperty, value); }
        }

        public static readonly new DependencyProperty HeightProperty =
            DependencyProperty.Register("Height", typeof(double), typeof(BorderWrapper), new FrameworkPropertyMetadata(
                default(double), FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.AffectsMeasure));

        // Wrapper Sides
        // Summary:
        //     Exposes the sides to the user as dependency property of type (FrameworkElement)
        private FrameworkElement left = null;
        public FrameworkElement Left
        {
            get { return left; }
            set
            {
                if (value != left)
                {
                    left = value;
                    OnPropertyChanged();
                }
            }
        }


        public FrameworkElement Top
        {
            get { return (FrameworkElement)GetValue(TopProperty); }
            set { SetValue(TopProperty, value); }
        }

        public static readonly DependencyProperty TopProperty =
            DependencyProperty.Register("Top", typeof(FrameworkElement), typeof(BorderWrapper), new FrameworkPropertyMetadata(
                null, FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.AffectsMeasure));

        public FrameworkElement Right
        {
            get { return (FrameworkElement)GetValue(RightProperty); }
            set { SetValue(RightProperty, value); }
        }

        public static readonly DependencyProperty RightProperty =
            DependencyProperty.Register("Right", typeof(FrameworkElement), typeof(BorderWrapper), new FrameworkPropertyMetadata(
                null, FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.AffectsMeasure));
        public FrameworkElement Bottom
        {
            get { return (FrameworkElement)GetValue(BottomProperty); }
            set { SetValue(BottomProperty, value); }
        }

        public static readonly DependencyProperty BottomProperty =
            DependencyProperty.Register("Bottom", typeof(FrameworkElement), typeof(BorderWrapper), new FrameworkPropertyMetadata(
                null, FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.AffectsMeasure));
        // Layout DependencyProperties
        // Summary:
        //     Border Decorations

        public CornerRadius CornerRadius
        {
            get { return (CornerRadius)GetValue(CornerRadiusProperty); }
            set { SetValue(CornerRadiusProperty, value); }
        }

        public static readonly DependencyProperty CornerRadiusProperty =
            DependencyProperty.Register("CornerRadius", typeof(CornerRadius), typeof(BorderWrapper), new FrameworkPropertyMetadata(
                default(CornerRadius), FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.AffectsMeasure));

        public Thickness BorderThickness
        {
            get { return (Thickness)GetValue(BorderThicknessProperty); }
            set { SetValue(BorderThicknessProperty, value); }
        }

        public static readonly DependencyProperty BorderThicknessProperty =
            DependencyProperty.Register("BorderThickness", typeof(Thickness), typeof(BorderWrapper), new FrameworkPropertyMetadata(
                default(Thickness), FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender));

        public Brush BorderBrush
        {
            get { return (Brush)GetValue(BorderBrushProperty); }
            set { SetValue(BorderBrushProperty, value); }
        }

        public static readonly DependencyProperty BorderBrushProperty =
            DependencyProperty.Register("BorderBrush", typeof(Brush), typeof(BorderWrapper), new FrameworkPropertyMetadata(
                default(Brush), FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender));
        #endregion
        // Public Members
        protected void OnPropertyChanged([CallerMemberName] string name = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }

        public event PropertyChangedEventHandler PropertyChanged;
        // Constructers
        public BorderWrapper()
        {
            //Add visuals to the VisualsCollection
            AddVisualChild(Left);
            AddVisualChild(Top);
            AddVisualChild(Right);
            AddVisualChild(Bottom);
        }
        //Override Members
        protected override int VisualChildrenCount => 5;
        #region Private Methods
        // Visuals Measurmment
        private Size MeasureVisuals(FrameworkElement child)
        {
            Trace.WriteLine("MeasureVisuals Called");
            Size totalSize = default;
            Size childSize = new Size(child.ActualWidth, child.ActualHeight);
            child.Measure(childSize);
            totalSize = SizeAddition(totalSize, childSize);
            if(Left != null)
            {
                Size leftSide = new Size(BorderThickness.Left, childSize.Height);
                Left.Measure(leftSide);
                totalSize = SizeAddition(totalSize, leftSide);
            }
            if(GetValue(TopProperty) != null)
            {
                Size topSize = new Size(childSize.Width, BorderThickness.Top);
                Top.Measure(topSize);
                totalSize = SizeAddition(totalSize, topSize);
            }
            if(GetValue(RightProperty) != null)
            {
                Size rightSize = new Size(BorderThickness.Right, childSize.Height);
                Right.Measure(rightSize);
                totalSize = SizeAddition(totalSize, rightSize);
            }
            if (GetValue(BottomProperty) != null)
            {
                Size bottomSize = new Size(childSize.Width, BorderThickness.Bottom);
                Bottom.Measure(bottomSize);
                totalSize = SizeAddition(totalSize, bottomSize);
            }
            return totalSize;
        }
        // Visuals Arrangement
        private Size ArrangeVisuals(FrameworkElement child)
        {
            Trace.WriteLine("ArrangeVisuals Called");
            Size totalSize = default;
            Size childSize = new Size(child.Width, child.Height);// !!
            child.Arrange(new Rect(new Point(BorderThickness.Left, BorderThickness.Top), childSize));
            Point c_Rel_P_Pos = child.TranslatePoint(new Point(0, 0), this);
            totalSize = SizeAddition(totalSize, childSize);
            if (Left != null)
            {
                Size leftSide = new Size(BorderThickness.Left, childSize.Height);
                Left.Arrange(new Rect(new Point(c_Rel_P_Pos.X - BorderThickness.Left, c_Rel_P_Pos.Y), leftSide));
                totalSize = SizeAddition(totalSize, leftSide);
            }
            if (GetValue(TopProperty) != null)
            {
                Size topSize = new Size(childSize.Width, BorderThickness.Top);
                Top.Arrange(new Rect(new Point(c_Rel_P_Pos.X, c_Rel_P_Pos.Y - BorderThickness.Top), topSize));
                totalSize = SizeAddition(totalSize, topSize);
            }
            if (GetValue(RightProperty) != null)
            {
                Size rightSize = new Size(BorderThickness.Right, childSize.Height);
                Right.Arrange(new Rect(new Point(c_Rel_P_Pos.X + childSize.Width, c_Rel_P_Pos.Y), rightSize));
                totalSize = SizeAddition(totalSize, rightSize);
            }
            if (GetValue(BottomProperty) != null)
            {
                Size bottomSize = new Size(childSize.Width, BorderThickness.Bottom);
                Bottom.Arrange(new Rect(new Point(c_Rel_P_Pos.X, c_Rel_P_Pos.Y + childSize.Height), bottomSize));
                totalSize = SizeAddition(totalSize, bottomSize);
            }
            return totalSize;
        }
        #endregion
        // Override Methods
        protected override Visual GetVisualChild(int index)
        {
            switch (index)
            {
                case 0: return Child;
                case 1: return Left;
                case 2: return Top;
                case 3: return Right;
                case 4: return Bottom;
                default: throw new ArgumentException(index + " index visual Is out of bounds");
            }
        }
        protected override Size MeasureOverride(Size constraint)
        {
            //Trace.WriteLine("MeasureOverride Called");
            Size visualsSize = constraint;
            if (Child is FrameworkElement child)
                visualsSize = MeasureVisuals(child);
            return visualsSize;
        }
        protected override Size ArrangeOverride(Size arrangeSize)
        {
            //Trace.WriteLine("ArrangeOverride Called");
            Size visualsArrangeSize = arrangeSize;
            if (Child is FrameworkElement child)
                visualsArrangeSize = ArrangeVisuals(child);
            return visualsArrangeSize;
        }
        private static Size SizeAddition(Size size1, Size size2)
        {
            return new Size(size1.Width + size2.Width, size1.Height + size2.Width);
        }
    }
}

和 xaml:

<cc:BorderWrapper BorderThickness="15" HorizontalAlignment="Left"
                          VerticalAlignment="Top">
            <cc:BorderWrapper.Left>
                <Rectangle>
                    <Rectangle.Style>
                        <Style TargetType="Rectangle">
                            <Setter Property="Fill" Value="Blue"/>
                            <Style.Triggers>
                                <Trigger Property="IsMouseOver" Value="True">
                                    <Setter Property="Fill" Value="Black"/>
                                </Trigger>
                            </Style.Triggers>
                        </Style>
                    </Rectangle.Style>
                </Rectangle>
            </cc:BorderWrapper.Left>
            <cc:BorderWrapper.Top>
                <Rectangle Fill="Green"/>
            </cc:BorderWrapper.Top>
            <cc:BorderWrapper.Right>
                <Rectangle Fill="DarkCyan"/>
            </cc:BorderWrapper.Right>
            <cc:BorderWrapper.Bottom>
                <Rectangle Fill="DarkMagenta"/>
            </cc:BorderWrapper.Bottom>

            <Rectangle Width="100" Height="100" Fill="Red"/>
        </cc:BorderWrapper>

但是当我将鼠标悬停在左矩形“边框”上时,颜色不会改变。 我做错了什么?

c# wpf xaml
1个回答
0
投票

我找到了一个似乎有效的解决方案,通过将“边界”从 DependencyProperties 更改为 Properties,如下所示。

private FrameworkElement _left;
[DefaultValue(null)]
public FrameworkElement Left
{
    get { return _left; }
    set
    {
        if (_left != value)
        {
            RemoveVisualChild(_left);
            RemoveLogicalChild(_left);
            _left = value;
            AddVisualChild(value);
            AddLogicalChild(value);
            InvalidateMeasure();
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.