查找动态生成的Storyboard实例(WPF)

时间:2012-06-01 09:15:34

标签: c# wpf asynchronous storyboard

我找到一个带有名称的生成故事板的问题。 我不能使用类变量,因为这个代码被多次调用,返回是异步的。

您可以查看我的其他问题以获取更多信息:Here

我的代码:

private void refreshPostIt(int index)
    {
        Button btn = // Button to rotate
        Storyboard sb = new Storyboard();
        sb.Name = "sb" + postItIndex;

        Storyboard.SetTarget(rotate, btn);
        Storyboard.SetTargetName(rotate, btn.Name);
        Storyboard.SetTargetProperty(rotate, new PropertyPath("(UIElement.RenderTransform).(RotateTransform.Angle)"));
        sb.Children.Add(rotate);
        sb.Begin(btn, true);

        // Asynchronous call
        BackgroundWorker bgw = new BackgroundWorker();
        bgw.DoWork += new DoWorkEventHandler(bgw_DoWork);
        bgw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgw_RunWorkerCompleted);
        bgw.RunWorkerAsync(postItIndex);
    }
private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        int postItIndex = // Retrieved from e.Arguments
        Button btn = // Find the Button thanks to the postItIndex

        Storyboard sb = // Here is my problem, how to find the Storyboard
        if (sb != null)
        {
            // Stop rotation
            //sb.Stop(btn);
        }
    }

2 个答案:

答案 0 :(得分:1)

总是可以创建一个继承自BackgroundWorker的类,它不是密封的。向该类添加一个属性,该属性包含您要传递给已完成事件的任何信息。

    class StoryboardWorkerArgs
    {
        public Storyboard StoryBoard { get; set; }
        public object Other { get; set; }
    }

    class BackgroundWorker2 : BackgroundWorker
    {
        public StoryboardWorkerArgs Args { get; set; }
    }

然后,您可以在args propety中设置故事板。

BackgroundWorker2 worker = new BackgroundWorker2();
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
worker.Args = new StoryboardWorkerArgs ()
{
  StoryBoard = null, /* reference to your storyboard*/
  Other = null, /* postItIndex */
 };
 worker.RunWorkerAsync();

然后在你完成的活动中。

void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    BackgroundWorker2 sender2 = sender as BackgroundWorker2;
    if (sender2 != null)
    {
        var story = sender2.Args.StoryBoard; // <- your storyboard.
    }
}

答案 1 :(得分:1)

如果您使用MVVM显示“postIt” - 启动和停止故事板将完全在XAML中。

在表示帖子的UIItem dataTemplate中有以下伪样式:

<Style>
    <Style.Triggers>
        <DataTrigger Binding="{Binding IsRefreshing}"
                     Value="True">
            <DataTrigger.EnterActions>
                <BeginStoryboard x:Name="rotating">
                    <Storyboard>
                        <DoubleAnimation... />
                    </Storyboard>
                </BeginStoryboard>
            </DataTrigger.EnterActions>
            <DataTrigger.ExitActions>
                <StopStoryboard BeginStoryboardName="rotating" />
            </DataTrigger.ExitActions>
        </DataTrigger>
    </Style.Triggers>
</Style>

你的viewmodel应该像(伪代码)一样:

Class MyApp : INotifyPropertyChanged
  ObservableCollection<Post> Posts {get;set;}
  void RefreshPost(int id);

Class Post : INotifyPropertyChanged
  bool IsRefreshing {get;set;}

在窗口中有一个带有ItemTemplate的listBox,并为Posts集合提供ItemsSource。

窗口的datacontext设置为MyApp的实例。 因此,每当你更改某些帖子的IsRrefreshing时,UI都会完成剩下的工作。