基于xaml代码构造变换组的WPF in-code [英] Constructing WPF in-code for transform group based on the xaml code
问题描述
我在构建我的wpf c#项目时遇到了问题。该项目假设为矩形设置动画以移动我之前设置的一定量的坐标。
例如:我的矩形位于(x = 0,y = 0)的位置。我想要点击一个按钮使其在100毫秒的间隔内移动到位置(x = 150,y = 230)。
但是,它无法运行并出现错误System.InvalidOperationException:'无法解析属性路径'RenderTransform.Children [2] .scaleY'中的所有属性引用。它突出了s.Begin(矩形);部分。
我尝试过:
这是xaml代码
I am having problem in constructing my wpf c# project. This project supposely to animate a rectangle to move a certain amount of coordinate that i have set earlier.
Ex: My rectangle is at the position (x=0,y=0). I want with a click of a button to make it move at position (x=150, y=230) in interval of 100 milliseconds.
However, it cannot run and come up with error "System.InvalidOperationException: 'Cannot resolve all property references in the property path 'RenderTransform.Children[2].scaleY'." And it's highlighting the s.Begin(rectangle); part.
What I have tried:
This is the xaml code
<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>
这是我的代码:< br $> b $ b
And this is my in code:
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);
}
推荐答案
如果存在,则无需在代码中创建Storyboard在XAML中。只需通过密钥引用XAML故事板并启动它:
You don't need to create the Storyboard in code if it exists in XAML. Simply reference the XAML Storyboard by its Key and start it:
Storyboard sb = this.FindResource("Storyboard1") as Storyboard;
sb.Begin();
如果StoryBoard没有TargetName,你可以设置一个:
If the StoryBoard does not have a TargetName, you can set one:
Storyboard sb = this.FindResource("Storyboard1") as Storyboard;
Storyboard.SetTarget(sb, rectangle);
sb.Begin();
更新
这是我发布的类似问题的答案。在这个解决方案中,他们想要一个只有XAML的解决方案 - 点击按钮并播放动画:
UPDATE
Here is an answer to a similar question that I posted. In this solution, they wanted to have a XAML only solution - click the button and play the animation:
<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>
Now, you want to call a storyboard against a UIElement from code-behind. So we want to change the button to raise an event and remove the Trigger for the button click event:
Now, you want to call a storyboard against a UIElement from code-behind. So we want to change the button to raise an event and remove the Trigger for the button click event:
<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>
Next we need to wire up the button event:
Next we need to wire up the button event:
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();
}
}
}
And bingo! The button is clicked, the code-behind is called, and the storyboard is found and started.
And bingo! The button is clicked, the code-behind is called, and the storyboard is found and started.
So is that mean i have to comment everything and make another function like i have done below?
So is that mean i have to comment everything and make another function like i have done below?
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);
}
}
}
这篇关于基于xaml代码构造变换组的WPF in-code的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!