1

Completed在a 事件的处理程序中Storyboard,我如何获取情节提要应用到的元素?

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

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

如果Completed我想抓取名为Container的网格,以便我可以用它的 DataContext 做一些讨厌的事情。可以做到这一点,还是我走错了路?

谢谢 :)

4

1 回答 1

2

对此的答案是这是不可能的——无论如何在 Silverlight 3 中都不可能。

使用调试器,我能够找到 Storyboard 的私有属性,当我沿着对象树向上走时,我到达了包含模板项 - 但是由于 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 ...
            }
        }
    }
}

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

于 2010-04-12T23:11:02.013 回答