wpfxamlanimationstoryboardvisualbrush

WPF - XAML - Call an animation in a nested style from the parent style


I'm trying to modify an ItemsControl to have a watermark to indicate the behavior of content dropped into it.

I'm using a Label inside a VisualBrush to show the word "OR" as the background to the ItemsControl (The control will contain property filters which will be Or'd together). The change in background is triggered by IsMouseOver on the ItemsControl.

The problem is this: I can get my VisualBrush (see xaml) to appear/disappear if I set the opacity directly in the Label but I cannot get the Opacity to animate if I try to use the nested style for the label. I have tried several approaches without success and so any pointers as to my mistake would be gratefully received.

I have included (one commented out) both animations I have tried. I also tried setting the Foreground on the Label with a ColorAnimation without success.

Many thanks Ian Carson

<ItemsControl x:Name="OrFilterItemsTarget"
              ItemsSource="{Binding Assets.OrFilters}"
              ItemTemplateSelector="{StaticResource FilterTargetTemplateSelector}"
              ItemContainerStyle="{StaticResource DraggableItemStyle}"
              BorderThickness="0,0,0,0.5"
              BorderBrush="DimGray"
              AllowDrop="True"
              IsHitTestVisible="True"
              Margin="0,2.95,15.934,77"
              HorizontalAlignment="Right"
              Width="105">
    <ItemsControl.Style>
        <Style TargetType="{x:Type ItemsControl}">
            <Style.Resources>
                <Style x:Key="LabelStyle"
                       TargetType="{x:Type Label}">
                    <Style.Resources>
                        <Storyboard x:Key="FadeUp">
                            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                                          Storyboard.TargetProperty="Opacity"
                                                          FillBehavior="HoldEnd">
                                <SplineDoubleKeyFrame KeyTime="00:00:2"
                                                     Value="0.5" />
                            </DoubleAnimationUsingKeyFrames>
                            <!--<DoubleAnimation Storyboard.TargetProperty="Opacity"
                                             From="0" To="0.5"
                                             Duration="0:0:2" />-->
                        </Storyboard>
                        <Storyboard x:Key="FadeDown">
                            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                                           Storyboard.TargetProperty="Opacity"
                                                           FillBehavior="Stop">
                                <SplineDoubleKeyFrame KeyTime="00:00:2"
                                                      Value="0" />
                            </DoubleAnimationUsingKeyFrames>
                            <!--<DoubleAnimation Storyboard.TargetProperty="Opacity"
                                             From="0.5" To="0"
                                             Duration="0:0:2" />-->
                        </Storyboard>
                    </Style.Resources>
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding Path=IsMouseOver, ElementName=OrFilterItemsTarget}"
                                     Value="True">
                            <DataTrigger.EnterActions>
                                <BeginStoryboard Storyboard="{StaticResource FadeUp}" />
                            </DataTrigger.EnterActions>
                        </DataTrigger>
                        <DataTrigger  Binding="{Binding Path=IsMouseOver, ElementName=OrFilterItemsTarget}"
                                      Value="False">
                            <DataTrigger.EnterActions>
                                <BeginStoryboard Storyboard="{StaticResource FadeDown}" />
                            </DataTrigger.EnterActions>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
                <VisualBrush x:Key="FilterContentType"
                             AlignmentX="Center"
                             AlignmentY="Center"
                             Stretch="None">
                    <VisualBrush.Visual>
                        <Label Content="OR"
                               Foreground="DarkGray"
                               Style="{StaticResource LabelStyle}">
                        </Label>
                    </VisualBrush.Visual>
                </VisualBrush>
            </Style.Resources>
            <Style.Triggers>
                <Trigger Property="IsMouseOver"
                         Value="True">
                    <Setter Property="Background"
                            Value="{StaticResource FilterContentType}" />
                </Trigger>
                <Trigger Property="IsMouseOver"
                         Value="False">
                    <Setter Property="Background"
                            Value="Transparent" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </ItemsControl.Style>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapPanel Orientation="Horizontal"
                       Background="Transparent">
                <i:Interaction.Behaviors>
                    <ei:FluidMoveBehavior AppliesTo="Children"
                                          Duration="0:0:0.3">
                        <ei:FluidMoveBehavior.EaseY>
                            <BackEase EasingMode="EaseIn"
                                      Amplitude="0.1" />
                        </ei:FluidMoveBehavior.EaseY>
                    </ei:FluidMoveBehavior>
                </i:Interaction.Behaviors>
            </WrapPanel>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>

Solution

  • In the end I realized I was over-thinking the problem. Nested styles were unnecessary. The solution was to set the background as the VisualBrush (with its content set up as the desired final appearance) inside its own tag within the ItemsControl and then animate the opacity of the VisualBrush using EventTriggers directly on the ItemsControl. Note the various events to manage both mouse and dragging user activity.

    Thanks to anyone who was thinking about this problem. The final XAML looks like this and hopefully will be useful to someone.

     <ItemsControl x:Name="OrFilterItemsTarget"
                   ItemsSource="{Binding Assets.OrFilters}"
                   ItemTemplateSelector="{StaticResource FilterTargetTemplateSelector}"
                   ItemContainerStyle="{StaticResource DraggableItemStyle}"
                   BorderThickness="0,0,0,0.5"
                   BorderBrush="DimGray"
                   AllowDrop="True"
                   IsHitTestVisible="True"
                   Margin="0,2.95,15.934,77"
                   HorizontalAlignment="Right"
                   Width="105">
         <ItemsControl.Background>
             <VisualBrush x:Name="OrFilterContentType"
                          AlignmentX="Center"
                          AlignmentY="Center"
                          Stretch="None"
                          Opacity="0">
                 <VisualBrush.Visual>
                     <Label Content="OR"
                            Foreground="DarkGray"
                            Opacity="0.5" />
                 </VisualBrush.Visual>
             </VisualBrush>
         </ItemsControl.Background>
         <ItemsControl.Triggers>
             <EventTrigger RoutedEvent="ItemsControl.MouseEnter">
                 <EventTrigger.Actions>
                     <BeginStoryboard>
                         <Storyboard>
                             <DoubleAnimation Storyboard.TargetName="OrFilterContentType"
                                              Storyboard.TargetProperty="(Brush.Opacity)"
                                              From="0" To="1"
                                              Duration="0:0:0.7" />
                         </Storyboard>
                     </BeginStoryboard>
                 </EventTrigger.Actions>
             </EventTrigger>
             <EventTrigger RoutedEvent="ItemsControl.DragEnter">
                 <EventTrigger.Actions>
                     <BeginStoryboard>
                         <Storyboard>
                             <DoubleAnimation Storyboard.TargetName="OrFilterContentType"
                                              Storyboard.TargetProperty="(Brush.Opacity)"
                                              From="0"
                                              To="1"
                                              Duration="0:0:0.7" />
                         </Storyboard>
                     </BeginStoryboard>
                 </EventTrigger.Actions>
             </EventTrigger>
             <EventTrigger RoutedEvent="ItemsControl.MouseLeave">
                 <EventTrigger.Actions>
                     <BeginStoryboard>
                         <Storyboard>
                             <DoubleAnimation Storyboard.TargetName="OrFilterContentType"
                                              Storyboard.TargetProperty="(Brush.Opacity)"
                                              From="1" To="0"
                                              Duration="0:0:0.7" />
                         </Storyboard>
                     </BeginStoryboard>
                 </EventTrigger.Actions>
             </EventTrigger>
             <EventTrigger RoutedEvent="ItemsControl.DragLeave">
                 <EventTrigger.Actions>
                     <BeginStoryboard>
                         <Storyboard>
                             <DoubleAnimation Storyboard.TargetName="OrFilterContentType"
                                              Storyboard.TargetProperty="(Brush.Opacity)"
                                              From="1"
                                              To="0"
                                              Duration="0:0:0.7" />
                         </Storyboard>
                     </BeginStoryboard>
                 </EventTrigger.Actions>
             </EventTrigger>
             <EventTrigger RoutedEvent="ItemsControl.Drop">
                 <EventTrigger.Actions>
                     <BeginStoryboard>
                         <Storyboard>
                             <DoubleAnimation Storyboard.TargetName="OrFilterContentType"
                                              Storyboard.TargetProperty="(Brush.Opacity)"
                                              From="1"
                                              To="0"
                                              Duration="0:0:0.7" />
                         </Storyboard>
                     </BeginStoryboard>
                 </EventTrigger.Actions>
             </EventTrigger>
         </ItemsControl.Triggers>
         <ItemsControl.ItemsPanel>
             <ItemsPanelTemplate>
                 <WrapPanel Orientation="Horizontal"
                            Background="Transparent">
                     <i:Interaction.Behaviors>
                         <ei:FluidMoveBehavior AppliesTo="Children"
                                               Duration="0:0:0.3">
                             <ei:FluidMoveBehavior.EaseY>
                                 <BackEase EasingMode="EaseIn"
                                           Amplitude="0.1" />
                             </ei:FluidMoveBehavior.EaseY>
                         </ei:FluidMoveBehavior>
                     </i:Interaction.Behaviors>
                 </WrapPanel>
             </ItemsPanelTemplate>
         </ItemsControl.ItemsPanel>
     </ItemsControl>