Member 13485513 Ответов: 2

Построение WPF in-кода для группы преобразований на основе кода xaml


У меня возникли проблемы при построении моего проекта wpf c#. Этот проект предположительно должен анимировать прямоугольник, чтобы переместить определенное количество координат, которые я установил ранее.
Пример: мой прямоугольник находится в положении (x=0,y=0). Я хочу одним нажатием кнопки заставить его двигаться в положении (x=150, y=230) с интервалом в 100 миллисекунд.
Однако он не может работать и придумать ошибку "система.InvalidOperationException: "не удается разрешить все ссылки на свойства в пути к свойству" RenderTransform.Children[2].scaleY'." и это выделение s.Begin(прямоугольник); part.

Что я уже пробовал:

Это код xaml

<Window x:Class="newStackOverflow.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:newStackOverflow"

        mc:Ignorable="d"

        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <Storyboard x:Key="Storyboard1">
            <DoubleAnimationUsingKeyFrames 

                Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)"

                Storyboard.TargetName="rectangle">
                <EasingDoubleKeyFrame KeyTime="0:0:10" Value="300"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Canvas x:Name="canvas1" VerticalAlignment="Stretch" Background="Green">
            <Rectangle x:Name="rectangle"

                       Fill="White" Stroke="Black"

                       Height="100" Width="100"

                       Canvas.Left="10" Canvas.Top="10"

                       RenderTransformOrigin="0.5,0.5">
                <Rectangle.RenderTransform>
                    <TransformGroup>
                        <ScaleTransform/>
                        <TranslateTransform/>
                    </TransformGroup>
                </Rectangle.RenderTransform>
            </Rectangle>
        </Canvas>
        <Button Content="Button"

                HorizontalAlignment="Center"

                VerticalAlignment="Center"

                Padding="10 5" Margin="10" Grid.Row="1">
            <Button.Triggers>
                <EventTrigger RoutedEvent="Button.Click">
                    <BeginStoryboard Storyboard="{StaticResource Storyboard1}"/>
                </EventTrigger>
            </Button.Triggers>
        </Button>

    </Grid>
</Window>



И это мой код:

public MainWindow()
       {
           InitializeComponent();


           Button button = new Button();
           button.Height = 28;
           button.Width = 58;
           button.HorizontalAlignment = HorizontalAlignment.Center;
           button.VerticalAlignment = VerticalAlignment.Center;
           button.Content = "Button";
           canvas1.Children.Add(button);

           button.Name = "button";

           this.RegisterName(button.Name, button);

           Rectangle rectangle = new Rectangle();
           rectangle.Width = 100;
           rectangle.Height = 100;
           rectangle.Fill = new SolidColorBrush(Colors.White);
           rectangle.Stroke = new SolidColorBrush(Colors.Black);
           Canvas.SetLeft(rectangle, 10);
           Canvas.SetTop(rectangle,10);
           canvas1.Children.Add(rectangle);

           rectangle.Name = "rectangle";


           TranslateTransform tt = new TranslateTransform();
           ScaleTransform st = new ScaleTransform();


           TransformGroup tg = new TransformGroup();
           tg.Children.Add(tt);
           tg.Children.Add(st);

           button.RenderTransform = tg;


           Duration duration = new Duration(TimeSpan.FromMilliseconds(10));
           DoubleAnimationUsingKeyFrames myDoubleAnim = new DoubleAnimationUsingKeyFrames();
           EasingDoubleKeyFrame myDoubleKey = new EasingDoubleKeyFrame();



           Storyboard s = new Storyboard();
           Storyboard.SetTargetName(myDoubleAnim, button.Name);
           Storyboard.SetTargetProperty(myDoubleAnim, new PropertyPath("RenderTransform.Children[1].scaleY"));

           myDoubleKey.KeyTime = KeyTime.FromPercent(1);
           myDoubleKey.Value = 300;
           myDoubleAnim.KeyFrames.Add(myDoubleKey);
           s.Children.Add(myDoubleAnim);

            s.Begin(rectangle);
           //button.Loaded += new RoutedEventHandler(buttonLoaded);


       }

2 Ответов

Рейтинг:
1

Graeme_Grant

Вам не нужно создавать раскадровку в коде, если она существует в XAML. Просто обратитесь к раскадровке XAML по ее ключу и запустите ее:

Storyboard sb = this.FindResource("Storyboard1") as Storyboard;
sb.Begin();

Если раскадровка не имеет целевого имени, вы можете установить его:
Storyboard sb = this.FindResource("Storyboard1") as Storyboard;
Storyboard.SetTarget(sb, rectangle);
sb.Begin();


ОБНОВЛЕНИЕ

Вот ответ на аналогичный вопрос, который я опубликовал. В этом решении они хотели иметь только решение XAML - нажмите кнопку и воспроизведите анимацию:
<Window x:Class="WpfRotateImage.MainWindow"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"



        mc:Ignorable="d"

        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"



        Title="WPF CodeProject Answer - Rotate Image" Height="350" Width="525">

    <Window.Resources>
        <Storyboard x:Key="Rotate">
            <ObjectAnimationUsingKeyFrames

                Storyboard.TargetProperty="(UIElement.Visibility)"

                Storyboard.TargetName="Image1">
                <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Hidden}"/>
                <DiscreteObjectKeyFrame KeyTime="0:0:0.1" Value="{x:Static Visibility.Visible}"/>
                <DiscreteObjectKeyFrame KeyTime="0:0:1" Value="{x:Static Visibility.Visible}"/>
                <DiscreteObjectKeyFrame KeyTime="0:0:1.01" Value="{x:Static Visibility.Hidden}"/>
            </ObjectAnimationUsingKeyFrames>
            <ObjectAnimationUsingKeyFrames

                Storyboard.TargetProperty="(UIElement.Visibility)"

                Storyboard.TargetName="Image2">
                <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}"/>
                <DiscreteObjectKeyFrame KeyTime="0:0:0.1" Value="{x:Static Visibility.Hidden}"/>
                <DiscreteObjectKeyFrame KeyTime="0:0:1.01" Value="{x:Static Visibility.Visible}"/>
            </ObjectAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames

                Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"

                Storyboard.TargetName="Image1">
                <EasingDoubleKeyFrame KeyTime="0:0:0.1" Value="1"/>
                <EasingDoubleKeyFrame KeyTime="0:0:1" Value="-1"/>
                <EasingDoubleKeyFrame KeyTime="0:0:1.2" Value="1"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
    </Window.Resources>
    <Window.Triggers>
        <EventTrigger RoutedEvent="ButtonBase.Click" SourceName="button">
            <BeginStoryboard Storyboard="{StaticResource Rotate}"/>
        </EventTrigger>
    </Window.Triggers>

    <Grid>
        <Grid.Resources>
            <Style TargetType="Image">
                <Setter Property="HorizontalAlignment" Value="Center"/>
                <Setter Property="VerticalAlignment" Value="Top"/>
                <Setter Property="Margin" Value="0 10 0 0"/>
                <Setter Property="Grid.ColumnSpan" Value="8"/>
                <Setter Property="Grid.RowSpan" Value="8"/>
                <Setter Property="Width" Value="100"/>
                <Setter Property="Height" Value="100"/>
            </Style>
            <Style TargetType="Button">
                <Setter Property="HorizontalAlignment" Value="Center"/>
                <Setter Property="VerticalAlignment" Value="Bottom"/>
                <Setter Property="Margin" Value="0 10"/>
                <Setter Property="Padding" Value="10 5"/>
                <Setter Property="Grid.ColumnSpan" Value="8"/>
                <Setter Property="Grid.RowSpan" Value="8"/>
            </Style>
        </Grid.Resources>

        <Image x:Name="Image1" Source="https://vc.vse.cz/wp-content/uploads/2014/08/Accept-icon.png"

               RenderTransformOrigin="0.5,0.5" Visibility="Hidden">
            <Image.RenderTransform>
                <TransformGroup>
                    <ScaleTransform/>
                    <SkewTransform/>
                    <RotateTransform/>
                    <TranslateTransform/>
                </TransformGroup>
            </Image.RenderTransform>
        </Image>
        <Image x:Name="Image2" Source="https://upload.wikimedia.org/wikipedia/commons/thumb/c/c0/MUTCD_R1-1.svg/2000px-MUTCD_R1-1.svg.png"/>

        <Button x:Name="button" Content="Animate"/>
    </Grid>

</Window>

Теперь вы хотите вызвать раскадровку против UIElement из code-behind. Поэтому мы хотим изменить кнопку, чтобы вызвать событие, и удалить триггер для события нажатия кнопки:
<Window x:Class="WpfRotateImage.MainWindow"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"



        mc:Ignorable="d"

        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"



        Title="WPF CodeProject Answer - Rotate Image" Height="350" Width="525">

    <Window.Resources>
        <Storyboard x:Key="Rotate">
            <ObjectAnimationUsingKeyFrames

                Storyboard.TargetProperty="(UIElement.Visibility)"

                Storyboard.TargetName="Image1">
                <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Hidden}"/>
                <DiscreteObjectKeyFrame KeyTime="0:0:0.1" Value="{x:Static Visibility.Visible}"/>
                <DiscreteObjectKeyFrame KeyTime="0:0:1" Value="{x:Static Visibility.Visible}"/>
                <DiscreteObjectKeyFrame KeyTime="0:0:1.01" Value="{x:Static Visibility.Hidden}"/>
            </ObjectAnimationUsingKeyFrames>
            <ObjectAnimationUsingKeyFrames

                Storyboard.TargetProperty="(UIElement.Visibility)"

                Storyboard.TargetName="Image2">
                <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}"/>
                <DiscreteObjectKeyFrame KeyTime="0:0:0.1" Value="{x:Static Visibility.Hidden}"/>
                <DiscreteObjectKeyFrame KeyTime="0:0:1.01" Value="{x:Static Visibility.Visible}"/>
            </ObjectAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames

                Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"

                Storyboard.TargetName="Image1">
                <EasingDoubleKeyFrame KeyTime="0:0:0.1" Value="1"/>
                <EasingDoubleKeyFrame KeyTime="0:0:1" Value="-1"/>
                <EasingDoubleKeyFrame KeyTime="0:0:1.2" Value="1"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
    </Window.Resources>

    <Grid>
        <Grid.Resources>
            <Style TargetType="Image">
                <Setter Property="HorizontalAlignment" Value="Center"/>
                <Setter Property="VerticalAlignment" Value="Top"/>
                <Setter Property="Margin" Value="0 10 0 0"/>
                <Setter Property="Grid.ColumnSpan" Value="8"/>
                <Setter Property="Grid.RowSpan" Value="8"/>
                <Setter Property="Width" Value="100"/>
                <Setter Property="Height" Value="100"/>
            </Style>
            <Style TargetType="Button">
                <Setter Property="HorizontalAlignment" Value="Center"/>
                <Setter Property="VerticalAlignment" Value="Bottom"/>
                <Setter Property="Margin" Value="0 10"/>
                <Setter Property="Padding" Value="10 5"/>
                <Setter Property="Grid.ColumnSpan" Value="8"/>
                <Setter Property="Grid.RowSpan" Value="8"/>
            </Style>
        </Grid.Resources>

        <Image x:Name="Image1" Source="https://vc.vse.cz/wp-content/uploads/2014/08/Accept-icon.png"

               RenderTransformOrigin="0.5,0.5" Visibility="Hidden">
            <Image.RenderTransform>
                <TransformGroup>
                    <ScaleTransform/>
                    <SkewTransform/>
                    <RotateTransform/>
                    <TranslateTransform/>
                </TransformGroup>
            </Image.RenderTransform>
        </Image>
        <Image x:Name="Image2" Source="https://upload.wikimedia.org/wikipedia/commons/thumb/c/c0/MUTCD_R1-1.svg/2000px-MUTCD_R1-1.svg.png"/>

        <Button x:Name="button" Content="Animate" Click="button_Click"/>
    </Grid>

</Window>

Далее нам нужно подключить событие кнопки:
using System.Windows;
using System.Windows.Media.Animation;

namespace WpfRotateImage
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void button_Click(object sender, RoutedEventArgs e)
        {
            var sb = FindResource("Rotate") as Storyboard;
            sb.Begin();
        }
    }
}

И бинго! Кнопка нажата, вызывается кодовая часть, и раскадровка найдена и запущена.


Member 13485513

я сделал изменения, как указано выше. Но вышла еще одна ошибка: "система.InvalidOperationException: свойство " [неизвестно]" не указывает на объект DependencyObject в path '(0).(1)[3].(2)'.' " и это указывает на СБ.();

Graeme_Grant

Я обновил решение с помощью рабочих примеров...

Member 13485513

Так значит ли это, что я должен все прокомментировать и сделать еще одну функцию, как я сделал ниже?

Graeme_Grant

А вы пробовали?

Вышеприведенные два примера в моем решении работают. Запустите новый проект, используйте код, запустите, и вы сможете увидеть его в действии.

Member 13485513

Да, я уже пробовал это. И реализовал его в своем проекте, и это сработало! Никогда не думал, что часть кода в коде так проста. Я попробовал сделать это в коде примерно через неделю. В любом случае спасибо:D

Рейтинг:
1

Member 13485513

Так значит ли это, что я должен все прокомментировать и сделать еще одну функцию, как я сделал ниже?

public MainWindow()
        {
            InitializeComponent();


            //Button button = new Button();
            //button.Height = 28;
            //button.Width = 58;
            //button.HorizontalAlignment = HorizontalAlignment.Center;
            //button.VerticalAlignment = VerticalAlignment.Center;
            //button.Content = "Button";
            //canvas1.Children.Add(button);

            //button.Name = "button";

            //this.RegisterName(button.Name, button);

            //Rectangle rectangle = new Rectangle();
            //rectangle.Width = 100;
            //rectangle.Height = 100;
            //rectangle.Fill = new SolidColorBrush(Colors.White);
            //rectangle.Stroke = new SolidColorBrush(Colors.Black);
            //Canvas.SetLeft(rectangle, 10);
            //Canvas.SetTop(rectangle, 10);
            //canvas1.Children.Add(rectangle);

            //rectangle.Name = "rectangle";


            //TranslateTransform tt = new TranslateTransform();
            //ScaleTransform st = new ScaleTransform();


            //TransformGroup tg = new TransformGroup();
            //tg.Children.Add(tt);
            //tg.Children.Add(st);

            //button.RenderTransform = tg;


            //Duration duration = new Duration(TimeSpan.FromMilliseconds(10));
            //DoubleAnimationUsingKeyFrames myDoubleAnim = new DoubleAnimationUsingKeyFrames();
            //EasingDoubleKeyFrame myDoubleKey = new EasingDoubleKeyFrame();



            //Storyboard s = this.FindResource("Storyboard1") as Storyboard;
            //Storyboard.SetTarget(s, rectangle);
            ////Storyboard.SetTargetProperty(s, new PropertyPath("RenderTransform.Children[1].scaleY"));

            //myDoubleKey.KeyTime = KeyTime.FromPercent(1);
            //myDoubleKey.Value = 300;
            //myDoubleAnim.KeyFrames.Add(myDoubleKey);
            //s.Children.Add(myDoubleAnim);

            ////s.Begin();
            //button.Loaded += new RoutedEventHandler(buttonLoaded);


        }

        private void buttonLoaded(object sender, RoutedEventArgs e)
        {
            Storyboard s = this.FindResource("Storyboard1") as Storyboard;
            s.Begin(this);
        }
    }
}