5

我正在尝试在 XAML 中创建一个故事板,该故事板为引发事件的元素的其中一个子元素的属性设置动画。但是如果不使用名称,我似乎无法让它工作,这是在这种特定情况下我无法真正做到的事情。

我基本上是在尝试这样的事情(当然要简化很多):

   <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>

关于如何实现这一点的任何想法?

4

2 回答 2

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>

请注意我是如何将 Button 添加到Trigger. 如果按钮低于Trigger您的问题,尝试访问Children[0]将抛出一个,ArgumentOutOfRangeException因为此时没有孩子。

于 2013-07-31T12:52:36.080 回答
1

Storyboard.TargetProperty在动画中使用 ,它应该始终是一个依赖属性。Children属性获取this ( )的一个UIElementCollection子元素。因此,下面的构造return应该会导致某个类型,以访问其依赖属性。PanelCanvasChildren [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或事件结束时访问 中的项目。否则,这些项目将不可用,因为它们未加载。

于 2013-07-30T05:40:06.097 回答