我正在尝试在XAML中创建一个故事板,该故事板为一个元素的一个子元素的属性设置动画,该元素会引发一个事件。但是我似乎无法在不使用Names的情况下使用它,这是我在这种特定情况下无法真正做到的事情。
我基本上都在尝试这样的事情(当然要简化得多):
<Canvas>
<Canvas.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Children[0].(Canvas.Left)" From="0" To="400" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Canvas.Triggers>
<Button Canvas.Left="20" Canvas.Top="20">A</Button>
<Button Canvas.Left="40" Canvas.Top="20">B</Button>
</Canvas>
关于如何实现这一目标的任何想法?
答案 0 :(得分:5)
假设您在动画中编入索引的UIElement
存在(即已存在于Canvas
),那么您可以执行以下操作:
<Canvas x:Name="MyCanvas">
<Button x:Name="btn" Canvas.Left="20" Canvas.Top="20">A</Button>
<Button Canvas.Left="40" Canvas.Top="20">B</Button>
<Canvas.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.Target="{Binding ElementName=MyCanvas, Path=Children[0]}"
Storyboard.TargetProperty="(Canvas.Left)" From="0" To="400" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Canvas.Triggers>
</Canvas>
请注意我如何移动Trigger
上方的按钮添加。如果按钮低于您问题中的Trigger
,则尝试访问Children[0]
会抛出ArgumentOutOfRangeException
,因为此时没有儿童。
答案 1 :(得分:1)
要在动画中使用Storyboard.TargetProperty
,它应该始终是依赖属性。 Children
属性获取此UIElementCollection
(Panel
)的子元素Canvas
。因此,以下构造Children [n]
返回UIElement
,它应该导致某种类型,以访问其依赖项属性。
这可以在代码中完成,如下所示:
Button MyButton = (Button)MyCanvas.Children[0];
MessageBox.Show(MyButton.Width.ToString());
默认情况下,动画中的所有这些操作都缺失,这是您的构造无法正常工作。
我建议在可能转换的代码中创建动画。
为了证明这一点,我在注册动画的Canvas
事件中创建了一个Loaded
。元素编号通过附加的依赖属性设置(当然,该示例可以以各种方式实现)。以下是我的例子:
XAML
<Grid>
<local:MyCanvas x:Name="MyCanvas" local:ClassForAnimation.Children="1">
<Button Canvas.Left="20" Canvas.Top="20">A</Button>
<Button Canvas.Left="40" Canvas.Top="20">B</Button>
</local:MyCanvas>
</Grid>
Code behind
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
public class MyCanvas : Canvas
{
public MyCanvas()
{
this.Loaded += new RoutedEventHandler(MyCanvas_Loaded);
}
private void MyCanvas_Loaded(object sender, RoutedEventArgs e)
{
MyCanvas myCanvas = sender as MyCanvas;
// Get No. of children
int children = ClassForAnimation.GetChildren(myCanvas);
// Get current Button for animation
Button MyButton = (Button)myCanvas.Children[children];
if (myCanvas != null)
{
DoubleAnimation doubleAnimation = new DoubleAnimation();
doubleAnimation.From = 0;
doubleAnimation.To = 400;
MyButton.BeginAnimation(Button.WidthProperty, doubleAnimation);
}
}
}
public class ClassForAnimation : DependencyObject
{
public static readonly DependencyProperty ChildrenProperty;
public static void SetChildren(DependencyObject DepObject, int value)
{
DepObject.SetValue(ChildrenProperty, value);
}
public static int GetChildren(DependencyObject DepObject)
{
return (int)DepObject.GetValue(ChildrenProperty);
}
static ClassForAnimation()
{
PropertyMetadata MyPropertyMetadata = new PropertyMetadata(0);
ChildrenProperty = DependencyProperty.RegisterAttached("Children",
typeof(int),
typeof(ClassForAnimation),
MyPropertyMetadata);
}
}
Note:
访问Canvas
中的项目只能在事件Loaded
或结束时进行。否则,项目不可用,因为它们未加载。