操纵Storyboard的目标对象

时间:2010-03-24 12:39:29

标签: animation silverlight-3.0 storyboard

Completed的{​​{1}}事件的处理程序中,如何获取故事板应用于的元素?

我的故事板是ItemTemplate的一部分:

Storyboard

<ListBox x:Name="MyListBox" > <ListBox.ItemTemplate> <DataTemplate> <Grid x:Name="Container" Height="30" > <Grid.Resources> <Storyboard x:Name="FadeOut" BeginTime="0:0:7" Completed="FadeOut_Completed"> <DoubleAnimation From="1.0" To="0.0" Duration="0:0:3" Storyboard.TargetName="Container" Storyboard.TargetProperty="Opacity" /> </Storyboard> </Grid.Resources> [...snip...] </Grid> </DataTemplate> </ListBox.ItemTemplate> </ListBox> 事件中,我想抓住名为 Container 的网格,以便我可以使用其DataContext进行讨厌的事情。可以这样做,还是我错误的方式?

谢谢:)

1 个答案:

答案 0 :(得分:2)

答案是,这是不可能的 - 不管是在Silverlight 3中。

使用调试器我能够找到故事板的私有属性,当我走到对象树时,我得到了包含模板项 - 但由于安全限制,我无法使用反射从代码中触摸它放在silverlight应用程序上(尽管这可能在WPF中可能)。

我的最终解决方案涉及使用Dictionary<Storyboard, Grid>和一些事件处理程序。使用模板我附加了Loaded处理程序,这意味着每次创建和加载模板的实例时(即对于绑定到列表框的每个数据项),都会调用我的处理程序。此时,我有一个模板的物理实例的引用,所以我可以搜索其子代的故事板:

private void ItemTemplate_Loaded(object sender, RoutedEventArgs e)
{
    Storyboard s = getStoryBoard(sender);
    if (s != null)
    {
        if (!_startedStoryboards.ContainsKey(s))
            _startedStoryboards.Add(s, (Grid)sender);
    }
}

private Storyboard getStoryBoard(object container)
{
    Grid g = container as Grid;
    if (g != null)
    {
        if (g.Resources.Contains("FadeOut"))
        {
            Storyboard s = g.Resources["FadeOut"] as Storyboard;
            return s;
        }
    }
    return null;
}

private Dictionary<Storyboard, Grid> _startedStoryboards = new Dictionary<Storyboard, Grid>();

然后当故事板的Completed事件被触发时,我可以轻松地使用这个字典作为查找来检索它所托管的项目模板,从那里我可以得到项目的DataContext模板并做我计划的令人讨厌的事情:

private void FadeOut_Completed(object sender, EventArgs e)
{
    if (_startedStoryboards.ContainsKey((Storyboard)sender))
    {
        Grid g = _startedStoryboards[(Storyboard)sender];
        if (g.DataContext != null)
        {
            MyDataItem z = g.DataContext as MyDataItem;

            if (z != null)
            {
                ... do my thing ...
            }
        }
    }
}

[注意:此代码已经过清理以供公众查看,请原谅您可能发现的任何小差异或语法错误]