Wpf 在XAML中动态修改路径、几何体和形状

Wpf 在XAML中动态修改路径、几何体和形状,wpf,xaml,data-binding,dependency-properties,Wpf,Xaml,Data Binding,Dependency Properties,我被卡住了。我想在XAML中制作一些复杂的动画,其中图像的几何体在运行时得到修改。我想从简单开始,然后做一些更有趣的事情,但似乎什么都不管用。 现在,我要做的就是使用For循环在屏幕上绘制一条弧,该弧将由滑块修改。滑块将控制圆弧的起点。因此,如果滑块位于Pi/4,它将从Pi/4到2Pi绘制一条弧 我试过很多不同的方法。现在我已经创建了一个类型为Shape的类,并尝试修改定义几何体,它是Shape类的一个属性。startRadians通过滑块进行修改,这样部件就可以正常工作了,我的绑定工作正常了。

我被卡住了。我想在XAML中制作一些复杂的动画,其中图像的几何体在运行时得到修改。我想从简单开始,然后做一些更有趣的事情,但似乎什么都不管用。 现在,我要做的就是使用For循环在屏幕上绘制一条弧,该弧将由滑块修改。滑块将控制圆弧的起点。因此,如果滑块位于Pi/4,它将从Pi/4到2Pi绘制一条弧

我试过很多不同的方法。现在我已经创建了一个类型为
Shape
的类,并尝试修改
定义几何体
,它是
Shape
类的一个属性。
startRadians
通过滑块进行修改,这样部件就可以正常工作了,我的绑定工作正常了。但是,在
startRadians
更改后(这是一个
dependencProperty
,顺便说一句),我希望类重新计算圆的几何体。(就像一个樱桃派,当
startRadians
被更改时,它缺少了一块更大的东西。)真正的问题是
DefiningGeometry
是一个只读属性,所以我不能动态更改它。(我说的对吗?)即使我可以,我也不知道如何编写代码行,以便
DrawMyArc
再次激发,结果重新加载到
DefiningGeometry

好的,我需要一些指导。我是否应该更改父类,以便具有易于修改的路径/几何体?我在这里不知所措

我是否应该使用完全不同的方法,例如使用StreamGeometry动态生成/删除几何体

以下是相关代码:

using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;


namespace January14noon
{
public class myCircle : Shape
{

    public double startRadians
    {
        get { return (double)GetValue(startRadiansProperty); }
        set { SetValue(startRadiansProperty, value); }
    }

    protected override Geometry DefiningGeometry
    {
        get
        {
            return DrawMyArc(100, 200, true, 40, 40, 360, startRadians, 2 * Math.PI);
        }
    }
    // Using a DependencyProperty as the backing store for startRadians.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty startRadiansProperty =
        DependencyProperty.Register("startRadians", typeof(double), typeof(myCircle), new PropertyMetadata(Math.PI / 4, new PropertyChangedCallback(startRadians_PropertyChanged)));

    private static void startRadians_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        //
        //    
    }
    public PathGeometry DrawMyArc(double centX, double centY, bool CW, double radiusX, double radiusY, int numberOfSegs, double startRad, double endRad)
    {
        double[,] rawPoints = new double[numberOfSegs, 2];
        List<LineSegment> segments = new List<LineSegment>();
        double arcLength;


            arcLength = endRad - startRad;
            for (int i = 0; i < numberOfSegs; i++)
            {
                rawPoints[i, 0] = radiusX * Math.Sin(i * (arcLength / numberOfSegs) + startRad) + centX;
                rawPoints[i, 1] = radiusY * -Math.Cos(i * (arcLength / numberOfSegs) + startRad) + centY;

                segments.Add(new LineSegment(new Point(rawPoints[i, 0], rawPoints[i, 1]), true));
            }

        LineSegment[] segArray = segments.ToArray();
        PathFigure figure = new PathFigure(new Point(centX, centY), segments, false);
        PathGeometry myGeometry = new PathGeometry();
        myGeometry.Figures.Add(figure);
        return myGeometry;
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Windows;
使用System.Windows.Media;
使用System.Windows.Shapes;
1月14日中午
{
公共类myCircle:形状
{
公共双星
{
获取{return(double)GetValue(startRadiansProperty);}
set{SetValue(startRadiansProperty,value);}
}
受保护的替代几何图形定义几何图形
{
收到
{
返回DrawMyArc(100200,true,40,40360,startRadians,2*Math.PI);
}
}
//使用DependencyProperty作为StartDians的后台存储。这将启用动画、样式、绑定等。。。
公共静态只读从属属性startRadiansProperty=
DependencyProperty.Register(“StartDians”、typeof(double)、typeof(myCircle)、new PropertyMetadata(Math.PI/4、new PropertyChangedCallback(StartDians_PropertyChanged));
私有静态void startDians\u属性已更改(DependencyObject d、DependencyPropertyChangedEventArgs e)
{
//
//    
}
公共路径几何图形DrawMyArc(双中心、双中心、布尔CW、双半径X、双半径Y、整数段、双起点、双终点)
{
double[,]rawPoints=新的double[numberOfSegs,2];
列表段=新列表();
双弧长;
弧长=endRad-startRad;
对于(int i=0;i
}

和XAML:

<Window x:Class="January14noon.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:January14noon"
    mc:Ignorable="d"


    Title="MainWindow" Height="350" Width="525">
<Window.Resources>
    <local:myCircle x:Key="myCircleDataSource" d:IsDataSource="True"/>
</Window.Resources>
<Grid DataContext="{Binding Source={StaticResource myCircleDataSource}}">
    <Slider x:Name="slider" VerticalAlignment="Top" Margin="0,0,163.898,0" Value="{Binding startRadians, Mode=OneWayToSource}"/>
    <TextBox x:Name="myTextBox" HorizontalAlignment="Right" Height="23" TextWrapping="Wrap" Text="{Binding startRadians}" VerticalAlignment="Top" Width="147.797"/>
    <!--<local:myCircle x:Name="instanceOfCircle" />-->
    <local:myCircle Stroke="Black" StrokeThickness="2"/>

</Grid>

任何帮助都将不胜感激。只是一般的方法,一些具体的东西,甚至是鼓励的话


TYIA

确保将可见圆绑定到数据源:

<Window.Resources>
    <local:myCircle x:Key="myCircleDataSource" d:IsDataSource="True"/>
</Window.Resources>
<Grid DataContext="{Binding Source={StaticResource myCircleDataSource}}">
    <Slider x:Name="slider" VerticalAlignment="Top" Margin="0,0,163.898,0" Value="{Binding startRadians, Mode=OneWayToSource}"/>
    <TextBox x:Name="myTextBox" HorizontalAlignment="Right" Height="23" TextWrapping="Wrap" Text="{Binding startRadians}" VerticalAlignment="Top" Width="147.797"/>
    <!--<local:myCircle x:Name="instanceOfCircle" />-->
    <local:myCircle Stroke="Black" StrokeThickness="2" startRadians="{Binding startRadians}"/>

</Grid>

并在属性更改时使视觉效果无效:

private static void startRadians_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var circle = (myCircle)d;  
    circle.InvalidateVisual(); // <-- Invalidate!
}
private static void startDians\u属性已更改(DependencyObject d、DependencyPropertyChangedEventArgs e)
{
var循环=(myCircle)d;

circle.InvalidateVisual();//确保将可见圆绑定到数据源:

<Window.Resources>
    <local:myCircle x:Key="myCircleDataSource" d:IsDataSource="True"/>
</Window.Resources>
<Grid DataContext="{Binding Source={StaticResource myCircleDataSource}}">
    <Slider x:Name="slider" VerticalAlignment="Top" Margin="0,0,163.898,0" Value="{Binding startRadians, Mode=OneWayToSource}"/>
    <TextBox x:Name="myTextBox" HorizontalAlignment="Right" Height="23" TextWrapping="Wrap" Text="{Binding startRadians}" VerticalAlignment="Top" Width="147.797"/>
    <!--<local:myCircle x:Name="instanceOfCircle" />-->
    <local:myCircle Stroke="Black" StrokeThickness="2" startRadians="{Binding startRadians}"/>

</Grid>

并在属性更改时使视觉效果无效:

private static void startRadians_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var circle = (myCircle)d;  
    circle.InvalidateVisual(); // <-- Invalidate!
}
private static void startDians\u属性已更改(DependencyObject d、DependencyPropertyChangedEventArgs e)
{
var循环=(myCircle)d;

circle.InvalidateVisual();//任何影响控件视觉外观的依赖项属性都可以注册到相应的数据库中,例如
影响度量
影响范围
影响范围

还要注意,C#中的类、属性和方法名称应该使用Pascal大小写,即以大写字母开头

public static readonly DependencyProperty StartRadiansProperty =
    DependencyProperty.Register(nameof(StartRadians), typeof(double), typeof(MyCircle),
    new FrameworkPropertyMetadata(Math.PI / 4,
        FrameworkPropertyMetadataOptions.AffectsMeasure, StartRadiansPropertyChanged));

public double StartRadians
{
    get { return (double)GetValue(StartRadiansProperty); }
    set { SetValue(StartRadiansProperty, value); }
}

private static void StartRadiansPropertyChanged(
    DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    ...
}

任何影响控件视觉外观的依赖项属性都可以注册到相应的数据库中,例如
AffectsMeasure
affectsRange
AffectsRender

还要注意,C#中的类、属性和方法名称应该使用Pascal大小写,即以大写字母开头

public static readonly DependencyProperty StartRadiansProperty =
    DependencyProperty.Register(nameof(StartRadians), typeof(double), typeof(MyCircle),
    new FrameworkPropertyMetadata(Math.PI / 4,
        FrameworkPropertyMetadataOptions.AffectsMeasure, StartRadiansPropertyChanged));

public double StartRadians
{
    get { return (double)GetValue(StartRadiansProperty); }
    set { SetValue(StartRadiansProperty, value); }
}

private static void StartRadiansPropertyChanged(
    DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    ...
}

谢谢,工作得很有魅力。谢谢你抓到了那个失踪的“失效事件”在过去的两个月里,我一直在钻研xaml,但从未见过它被使用。调用InvalidateVisual是一种黑客行为。注意:此方法通常不会从应用程序代码中调用……仅在高级方案中需要调用此方法。其中一种高级方案是,如果您正在为依赖项属性创建PropertyChangedCallbackrty不在Freezable或FrameworkElement派生类上,该派生类在布局更改时仍会影响布局。这里不是这种情况。如果要正确执行此操作,请设置FrameworkPropertyMetadataOptions。@SojourningStudent,请