Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Storyboard not found in name scope of style

The problem I'm having is that if I base a style on a second style that contains a storyboard, then there is an exception in the Trigger.ExitAction.

  • If I mouse over either of the rectangles in the demo below then the storyboard will run and the rectangles change colour.
  • When the mouse leaves the red rectangle with style='rectStyle' the storyboard is removed.
  • When the mouse leaves the blue rectangle (which uses the derived style) I get this exception:

    InvalidOperationException: 'MouseOverStoryboard' name cannot be found in the name scope of 'System.Windows.Style'.

So:

  • Is it valid to have a storyboard in a base style?
  • Is there a more explicit way of referring to the BeginStoryboardName so that this error doesn't occur?
  • Any other suggestions?

In the end what I'm trying to achieve re-use a style containing triggers and storyboards in several other styles.

Here's some simple code that demonstrates the problem:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition/>
    </Grid.RowDefinitions>

    <Grid.Resources>
        <Style x:Key="rectStyle" TargetType="{x:Type Rectangle}">
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Trigger.EnterActions>
                        <BeginStoryboard x:Name="MouseOverStoryboard">
                            <Storyboard>
                                <ColorAnimation To="PaleGoldenrod" 
                                   Storyboard.TargetProperty="(Fill).(Color)" 
                                   Duration="0:0:1"/>
                            </Storyboard>
                        </BeginStoryboard>
                    </Trigger.EnterActions>
                    <Trigger.ExitActions>
                        <StopStoryboard BeginStoryboardName="MouseOverStoryboard"/>
                    </Trigger.ExitActions>
                </Trigger>
            </Style.Triggers>
        </Style>

        <Style x:Key="rectStyle2" TargetType="{x:Type Rectangle}" 
               BasedOn="{StaticResource rectStyle}"/>
    </Grid.Resources>

    <Rectangle Grid.Row="0" Width="100" Height="100" Fill="Red" 
               Style="{StaticResource rectStyle}" />
    <Rectangle Grid.Row="1" Width="100" Height="100" Fill="Blue" 
               Style="{StaticResource rectStyle2}" />
</Grid>
like image 293
Phil Avatar asked Mar 29 '12 07:03

Phil


1 Answers

Your best bet is to steer clear of derived styles if you want to include StopStoryboard. There are actually 2 instances of the style and the scope is wrong for the derived style. I believe this is by design. You could abstract that storyboard out to an outer scope in the resources and duplicate the triggers in both styles, referencing the Storyboard by StaticResource. It may not solve your problem since you may have a specific requirement for derived styles, but I don't think you have a choice unfortunately.

Because you cannot inherit from a base style at all if you want to use StopStoryboard you'd have to do something like this:

<Grid>
<Grid.RowDefinitions>
  <RowDefinition/>
  <RowDefinition/>
</Grid.RowDefinitions>
<Grid.Resources>
  <Storyboard x:Key="mouseOver">
    <ColorAnimation
      AutoReverse="True"
      Duration="0:0:1"
      RepeatBehavior="Forever"
      Storyboard.TargetProperty="(Fill).(Color)"
      To="PaleGoldenrod"/>
  </Storyboard>
  <Style x:Key="rectStyle" TargetType="{x:Type Rectangle}">
    <Style.Triggers>
      <Trigger Property="IsMouseOver" Value="True">
        <Trigger.EnterActions>
          <BeginStoryboard x:Name="MouseOverStoryboard" Storyboard="{StaticResource mouseOver}"/>
        </Trigger.EnterActions>
        <Trigger.ExitActions>
          <StopStoryboard BeginStoryboardName="MouseOverStoryboard"/>
        </Trigger.ExitActions>
      </Trigger>
    </Style.Triggers>
  </Style>
  <Style x:Key="rectStyle2" TargetType="{x:Type Rectangle}">
    <Style.Triggers>
      <Trigger Property="IsMouseOver" Value="True">
        <Trigger.EnterActions>
          <BeginStoryboard x:Name="MouseOverStoryboard1" Storyboard="{StaticResource mouseOver}"/>
        </Trigger.EnterActions>
        <Trigger.ExitActions>
          <StopStoryboard BeginStoryboardName="MouseOverStoryboard1"/>
        </Trigger.ExitActions>
      </Trigger>
    </Style.Triggers>
  </Style>
</Grid.Resources>
<Rectangle
  Width="100"
  Height="100"
  Grid.Row="0"
  Fill="Red"
  Style="{StaticResource rectStyle}"/>
<Rectangle
  Width="100"
  Height="100"
  Grid.Row="1"
  Fill="Blue"
  Style="{StaticResource rectStyle2}"/>

like image 141
erodewald Avatar answered Oct 29 '22 00:10

erodewald