Почему я не могу установить непрозрачность в этой ситуации?

Вот ситуация... на верхнем уровне у меня есть TabControl. Каждая страница в TabControl состоит из 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>

ListBox имеют горизонтально ориентированную StackPanel в качестве своего 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>

Вы заметите, что у меня есть несколько обработчиков событий на этой панели стека. Они предназначены для анимации элементов на панели стека, поэтому они последовательно исчезают. Обработчики событий реализованы как:

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);
    }
}

По большей части это прекрасно работает. Когда вы впервые нажимаете (или загружаете) вкладку, подэлементы на панели стека появляются один за другим. Проблема заключается в том, что когда вы снова нажимаете на вкладку, которая уже была показана ранее (т. е. вы находитесь в обработчике события "VisibleChanged", а не в обработчике "Loaded"), все элементы уже отображаются, и они мигают. по порядку, а не начинаться со скрытого и отображаться по порядку.

Вот где это становится некрасиво. Эта строка:

panel.Children[i].Opacity = 0.0;

... ничего не делает. Если я пройдусь по коду в отладчике и поставлю часы на "panel.Children[i].Opacity", он останется на уровне 1.0. Никаких исключений или чего-то подобного. Это просто... не работает.

Любые идеи?


person dkeen    schedule 30.03.2009    source источник
comment
Проверьте окно вывода, во многих случаях wpf не генерирует исключений, а записывает в окно вывода.   -  person John    schedule 31.03.2009
comment
Там ничего не всплыло, но хороший совет (особенно для WPF n00b, такого как я).   -  person dkeen    schedule 31.03.2009


Ответы (1)


У меня есть предположение, что может произойти: WPF не удаляет анимацию после ее завершения, поэтому, когда ваш код выполняет метод applySubItemsAnimations во второй раз, предыдущие анимации все еще существуют. Поэтому вы можете попытаться удалить эти анимации, передав null в качестве второго параметра для

panel.Children[i].BeginAnimation(UIElement.OpacityProperty, null);

После этого вы можете применить новую анимацию, чтобы весь for-цикл выглядел так:

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, null);        
    panel.Children[i].BeginAnimation(UIElement.OpacityProperty, fadeIn);        
}
person EFrank    schedule 31.03.2009
comment
Была точно такая же проблема, как и эта, и, как ни странно, похоже, что dkeen пишет почти такой же тип управления, как и я! Спасибо. - person Luke Puplett; 27.11.2009