Here's the situation... at the top level, I have a TabControl. Each page in the TabControl consists of a ListBox:
<TabControl>
<TabItem Header="item 1">
<ListBox>
<ListBoxItem>sub item 1</ListBoxItem>
<ListBoxItem>sub item 2</ListBoxItem>
<ListBoxItem>sub item 3</ListBoxItem>
</ListBox>
</TabItem>
<TabItem Header="item 2">
<ListBox>
<ListBoxItem>sub item 1</ListBoxItem>
<ListBoxItem>sub item 2</ListBoxItem>
</ListBox>
</TabItem>
</TabControl>
The ListBoxes have a horizontally-oriented StackPanel as their ListTemplate:
<Style TargetType="ListBox">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"
VisibleChanged="onStackPanelVisibilityChange"
Loaded="onStackPanelLoaded"
VerticalAlignment="Center" HorizontalAlignment="Center" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
You'll notice I have some event handlers on that stack panel. Those are to animate the items within the stack panel, so they fade into view sequentially. The event handlers are implemented as:
void onStackPanelLoaded(object sender, RoutedEventArgs e)
{
StackPanel panel = sender as StackPanel;
applySubItemAnimations(panel);
}
void onStackPanelVisibilityChange(object sender, DependencyPropertyChangedEventArgs e)
{
StackPanel panel = sender as StackPanel;
if (panel.IsVisible)
{
applySubItemAnimations(panel);
}
}
private void applySubItemAnimations(StackPanel panel)
{
DoubleAnimation fadeIn = new DoubleAnimation();
fadeIn.DecelerationRatio = 0.1;
fadeIn.Duration = new Duration(new TimeSpan(0, 0, 0, 0, 500));
fadeIn.From = 0.0;
fadeIn.To = 1.0;
for (int i = 0; i < panel.Children.Count; i++)
{
panel.Children[i].Opacity = 0.0;
fadeIn.BeginTime = new TimeSpan(0, 0, 0, 0, 200 * i + 50);
panel.Children[i].BeginAnimation(UIElement.OpacityProperty, fadeIn);
}
}
For the most part, this works great. When you first click on (or load) a tab, the sub-items in the stack panel fade into view one-after-the-other. The problem is when you click back to a tab that's already been shown once before (ie, you're in the "VisibleChanged" event handler rather than the "Loaded" handler), all the items are already shown and they blink in order, rather than starting as hidden and being shown in order.
Here's where it gets ugly. This line:
panel.Children[i].Opacity = 0.0;
... does nothing. If I step through the code in the debugger and put a watch on "panel.Children[i].Opacity", it stays right at 1.0. No exception or anything. It just... doesn't work.
Any ideas?