绑定到类的依赖项属性时,绑定不起作用(仅一种方式)

时间:2019-10-22 13:21:24

标签: c# wpf data-binding

我正在尝试将滑块绑定到继承自shape的类的依赖项属性,但似乎只能以一种方式工作(从类到滑块)。如果我通过它后面的代码设置属性,并且滑块会更新

感谢任何想法或帮助

<Window x:Class="Controls.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:Controls"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800">
<Grid>
    <Grid>
        <StackPanel>
            <Border Width="200" Height="200">
                <local:Pie x:Name="piece1"   StartAngle="45" EndAngle="90"/>
            </Border>
            <Slider Maximum="360" Minimum="0" Value="{Binding Path=StartAngle, ElementName=piece1, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></Slider>
            <Button Content="Move" Width="100" HorizontalAlignment="Left" VerticalAlignment="Top" Click="Button_Click" />
        </StackPanel>
    </Grid>
</Grid>
</Window>

这是我要绑定的类。基本上是创建一种饼图/切片。

using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;

namespace Controls
{
    public class Pie : Shape
    {

        public static readonly DependencyProperty StartAngleProperty = 
            DependencyProperty.Register("StartAngle", typeof(int), typeof(Pie), 
            new PropertyMetadata(default(int)));

        public static readonly DependencyProperty EndAngleProperty = 
            DependencyProperty.Register("EndAngle", typeof(int), typeof(Pie), 
            new PropertyMetadata(default(int)));

        public int StartAngle
        {
            get { return (int) GetValue(StartAngleProperty); }
            set
            { 
                SetValue(StartAngleProperty, value);
                InvalidateVisual();
            }
        }
        public int EndAngle
        {
            get { return (int)GetValue(EndAngleProperty); }
            set
            {
                SetValue(EndAngleProperty, value);
                InvalidateVisual();
            }
        }

        private const int CenterX = 100;
        private const int CenterY = 100;
        private const int Radius = 100;


        private double Angle
        {
            get
            {
                if (StartAngle > EndAngle)
                    return (360 - StartAngle) + EndAngle;

                return EndAngle - StartAngle;

                //return (360 - StartAngle) + EndAngle;
            }
        }

        public Pie()
        {
            Fill = (SolidColorBrush)(new BrushConverter().ConvertFrom("#4386D8"));
            Stroke = Brushes.Black;
            StrokeThickness = 1;
        }

        public static Point ComputeCartesianCoordinate(double angle, double radius)
        {
            // convert to radians
            double angleRad = (Math.PI / 180.0) * (angle - 90);

            double x = radius * Math.Cos(angleRad);
            double y = radius * Math.Sin(angleRad);

            return new Point(x, y);
        }

        protected override Geometry DefiningGeometry
        {
            get
            {
                StreamGeometry geometry = new StreamGeometry();
                geometry.FillRule = FillRule.EvenOdd;

                using (StreamGeometryContext context = geometry.Open())
                {
                    DrawGeometry(context);
                }

                geometry.Freeze();

                return geometry;
            }
        }

        private void DrawGeometry(StreamGeometryContext context)
        {
            Point startPoint = new Point(CenterX, CenterY);

            Point outerArcStartPoint = ComputeCartesianCoordinate(StartAngle, Radius);
            outerArcStartPoint.Offset(CenterX, CenterY);

            Point outerArcEndPoint = ComputeCartesianCoordinate(StartAngle + Angle, Radius);
            outerArcEndPoint.Offset(CenterX, CenterY);

            bool largeArc = Angle > 180.0;
            Size outerArcSize = new Size(Radius, Radius);

            context.BeginFigure(startPoint, true, true);
            context.LineTo(outerArcStartPoint, true, true);
            context.ArcTo(outerArcEndPoint, outerArcSize, 0, largeArc, SweepDirection.Clockwise, true, true);
        }
    }
}

1 个答案:

答案 0 :(得分:1)

实际上 都正确地以两种方式更改了值,您会用Debug.Print注意到它。仅,执行Binding时,框架不一定会调用属性的setter。代码中的问题是,您正在InvalidateVisual()属性的设置器中执行StartAngle,但是正如MSDN指出的here

  

在所有例外情况下,包装器实现   应该分别仅执行GetValue和SetValue操作。   原因在主题XAML加载和   依赖项属性。

您应该改为声明DependencyProperty,以便使用FrameworkPropertyMetadata对象在更新时自动使视觉无效:

public static readonly DependencyProperty StartAngleProperty = DependencyProperty.Register(
    "StartAngle",
    typeof(int),
    typeof(Pie),
    new FrameworkPropertyMetadata(default(int), FrameworkPropertyMetadataOptions.AffectsRender)
);

然后像这样离开您的吸气器/吸气器:

public int StartAngle {
    get { return (int)GetValue(StartAngleProperty); }
    set { SetValue(StartAngleProperty, value); }
}

现在,您将在移动滑块时看到控件的重绘。