WPF PropertyPath в пользовательском элементе управления

У меня проблема, я создаю элемент управления с именем Tile (например, Tile в Windows 10). Эта плитка имитирует трехмерное вращение с помощью класса проекции, такого как класс проекции в Silverlight.

У нас есть базовый класс проекции, подобный этому:

abstract public class Projection
    : FrameworkElement
{
    static public readonly DependencyProperty RotationZProperty = DependencyProperty.Register(
          nameof(RotationZ),
          typeof(double),
          typeof(Projection),
          new UIPropertyMetadata(0.0, OnRotationChanged));

    static public readonly DependencyProperty RotationYProperty = DependencyProperty.Register(
            nameof(RotationY),
            typeof(double),
            typeof(Projection),
            new UIPropertyMetadata(0.0, OnRotationChanged));

    static public readonly DependencyProperty RotationXProperty = DependencyProperty.Register(
            nameof(RotationX),
            typeof(double),
            typeof(Projection),
            new UIPropertyMetadata(0.0, OnRotationChanged));

public double RotationZ
{
    get { return this.GetValue<double>(RotationZProperty); }
    set { SetValue(RotationZProperty, value); }
}

public double RotationY
{
    get { return this.GetValue<double>(RotationYProperty); }
    set { SetValue(RotationYProperty, value); }
}

public double RotationX
{
    get { return this.GetValue<double>(RotationXProperty); }
    set { SetValue(RotationXProperty, value); }
}

public FrameworkElement Child
{
    get;
    set;
}

static private void OnRotationChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is Projection pl)
            {
                pl.OnRotationChanged();
            }
        }

        private void OnRotationChanged()
        {
            // Some code
        }}

After that, we have the PlaneProjectionClass :

     [ContentProperty("Child")]
    sealed public class PlaneProjection
        : Projection
    {   
    }

Класс Tile использует свойство зависимостей типа Projection:

     public class Tile
    {
     static public readonly DependencyProperty PlaneProjectionProperty = DependencyProperty.Register(
            nameof(Projection),
            typeof(Projection),
            typeof(Tile),
            new UIPropertyMetadata());

 public Projection Projection
        {
            get { return (Projection)GetValue(PlaneProjectionProperty); }
            private set { SetValue(PlaneProjectionProperty, value); }
        }

        override public void OnApplyTemplate()
        {
            Projection = GetTemplateChild("PART_Projection") as Projection;
        }
     }

Итак, для XAML у нас есть это в ControlTemplate:

    <controls:PlaneProjection x:Name="PART_PlaneProjection">
    <Border>
    <Grid>
      <!-- Some design -->
    </Grid>
    </Border>
</controls:PlaneProjection>

Теперь я хотел бы анимировать проекцию плоскости.

Итак, я создаю раскадровку и анимирую проекцию с помощью rotateX:

static public void CreateAnimation(Tile tile)
{
    Storyboard.SetTarget(anim, tile);
    Storyboard.SetTargetProperty(doubleAnim, new PropertyPath("(Tile.Projection).(PlaneProjection.RotationX"));
 }

Но при отладке у меня возникает эта ошибка: не удается разрешить все ссылки на свойство по пути свойства '(Tile.Projection).(PlaneProjection.RotationX)

Я не понимаю ошибки :( Есть идеи по использованию PropertyPath в пользовательском элементе управления?


person Jérémy Janiszewski    schedule 18.07.2017    source источник


Ответы (1)


Свойство Projection в классе Tile не соответствует соглашениям об именах для свойств зависимостей.

Это должно, например. выглядеть так:

public static readonly DependencyProperty PlaneProjectionProperty =
    DependencyProperty.Register(nameof(PlaneProjection), typeof(Projection), typeof(Tile));

public Projection PlaneProjection
{
    get { return (Projection)GetValue(PlaneProjectionProperty); }
    private set { SetValue(PlaneProjectionProperty, value); }
}

Путь к свойству будет просто таким:

Storyboard.SetTargetProperty(anim, new PropertyPath("PlaneProjection.RotationX"));

Вам даже не понадобится раскадровка. Просто позвони

tile.PlaneProjection.BeginAnimation(Projection.RotationXProperty, anim);

Обратите внимание, что частный установщик не делает свойство зависимостей доступным только для чтения. См. Свойства зависимостей только для чтения подробности.

person Clemens    schedule 18.07.2017