在名称范围的样式中找不到故事板

时间:2012-03-29 07:22:41

标签: wpf xaml triggers styles storyboard

我遇到的问题是,如果我将样式基于包含故事板的第二种样式,那么Trigger.ExitAction就会出现异常。

  • 如果我鼠标悬停在下面演示中的任何一个矩形上,那么故事板将会运行并且矩形会改变颜色。
  • 当鼠标离开带有style ='rectStyle'的红色矩形时,故事板将被删除。
  • 当鼠标离开蓝色矩形(使用派生样式)时,我得到以下异常:

    InvalidOperationException异常: 在'System.Windows.Style'的名称范围内找不到'MouseOverStoryboard'名称。

所以:

  • 以基本风格制作故事板是否有效?
  • 是否有更明确的方式引用BeginStoryboardName以便不会发生此错误?
  • 还有其他建议吗?

最后,我试图重新使用包含其他几种风格的触发器和故事板的样式。

以下是一些演示此问题的简单代码:

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

2 个答案:

答案 0 :(得分:6)

如果要包含StopStoryboard,最好的办法是避免派生样式。实际上有2个样式的实例,并且派生样式的范围是错误的。我相信这是设计的。您可以将该故事板抽象到资源中的外部范围,并在两种样式中复制触发器,并通过StaticResource引用故事板。它可能无法解决您的问题,因为您可能对派生样式有特定要求,但我不认为您有不幸的选择。

因为如果你想使用StopStoryboard,你根本不能继承基础风格,你必须做这样的事情:

<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}"/>

答案 1 :(得分:2)

由于遇到同样的问题,偶然发现了这一点。还有另一个解决方案,虽然有些笨重。

在应用另一个动画时,属性上的动画会被覆盖,因此您可以使用触发器的ExitActions中的另一个BeginStoryboard覆盖前一个,并使用Stop的FillBehavior自动删除它。

不幸的是,Duration = 0,FillBehavior = Stop和没有目标值的组合不起作用,因此您需要为该动画设置非常短的持续时间。

在你的例子中:

<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>
                            <Storyboard>
                                <ColorAnimation To="PaleGoldenrod" 
                                   Storyboard.TargetProperty="(Fill).(Color)" 
                                   Duration="0:0:1"/>
                            </Storyboard>
                        </BeginStoryboard>
                    </Trigger.EnterActions>
                    <Trigger.ExitActions>
                        <BeginStoryboard>
                            <Storyboard FillBehavior="Stop">
                                <ColorAnimation 
                                   Storyboard.TargetProperty="(Fill).(Color)" 
                                   Duration="0:0:0.0000001"/>
                            </Storyboard>
                        </BeginStoryboard>
                    </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>