麻烦在WPF中设置RadialGradientBrush的动画

时间:2010-03-29 17:25:42

标签: wpf data-binding

我正在尝试在我的应用中为RadialGradientBrush设置动画。我得到了超级有用的例外:

Additional information: 'System.Windows.Style' value cannot be assigned to property 'Style' of object 'System.Windows.Controls.Border'. '[Unknown]' property does not point to a DependencyObject in path '(0).(1).[0].(2)'. Error at object 'System.Windows.Style' in markup file 'Eng.Modules.Core;component/system/grid/systemgridview.xaml' Line 252 Position 51.

我知道我的DoubleAnimation Storyboard.TargetProperty属性中的间接属性定位或部分路径限定有问题。有什么想法吗?

<Border>
  <Border.Resources>
    <RadialGradientBrush x:Key="SomeBrush">
      <RadialGradientBrush.GradientStops>
        <GradientStop Color="White" Offset="0" />
        <GradientStop Color="Gold" Offset="1" />
      </RadialGradientBrush.GradientStops>
    </RadialGradientBrush>
  </Border.Resources>
  <Border.Style>
    <Style TargetType="{x:Type Border}">
      <Style.Triggers>
        <DataTrigger Binding="{Binding Path=IsEnabled, RelativeSource={RelativeSource Self}}" Value="True">
          <Setter Property="Background" Value="{StaticResource SomeBrush}" />
          <DataTrigger.EnterActions>
            <BeginStoryboard x:Name="SomeStoryBoard">
              <Storyboard>
                <!-- RIGHT HERE -->
                <DoubleAnimation
                  Storyboard.TargetProperty="(Border.Background).(GradientBrush.GradientStops)[0].(GradientStop.Offset)"
                  From="0" To="1" Duration="0:0:1"
                  RepeatBehavior="Forever"
                  AutoReverse="True" />
              </Storyboard>
            </BeginStoryboard>
          </DataTrigger.EnterActions>
          <DataTrigger.ExitActions>
            <RemoveStoryboard BeginStoryboardName="SomeStoryBoard" />
          </DataTrigger.ExitActions>
        </DataTrigger>
      </Style.Triggers>
    </Style>
  </Border.Style>
</Border>

3 个答案:

答案 0 :(得分:1)

第一个问题是您将背景设置为DataTrigger中的渐变画笔。因为这会在以后应用,动画将无法找到画笔(因此无法找到依赖属性的神秘错误)。所以我做的第一件事就是手动将边框的背景设置为画笔,而不是触发器。

第二个问题是你如何设置目标属性。您不需要使用括号语法 - 它可以正常工作,如下所示:Background.GradientStops[0].Offset

通过这些变化,边框可以完美地动画;这是最后的加价:

<Border>
    <Border.Background>
        <RadialGradientBrush>
            <RadialGradientBrush.GradientStops>
                <GradientStop Color="White" Offset="0" />
                <GradientStop Color="Gold" Offset="1" />
            </RadialGradientBrush.GradientStops>
        </RadialGradientBrush>
    </Border.Background>
    <Border.Style>
        <Style TargetType="{x:Type Border}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding Path=IsEnabled, RelativeSource={RelativeSource Self}}" Value="True">
                    <DataTrigger.EnterActions>
                        <BeginStoryboard x:Name="SomeStoryBoard">
                            <Storyboard>
                                <!-- RIGHT HERE -->
                                <DoubleAnimation 
                                      Storyboard.TargetProperty="Background.GradientStops[0].Offset"
                                      From="0" To="1" Duration="0:0:1"
                                      RepeatBehavior="Forever"
                                      AutoReverse="True" />
                            </Storyboard>
                        </BeginStoryboard>
                    </DataTrigger.EnterActions>
                    <DataTrigger.ExitActions>
                        <RemoveStoryboard BeginStoryboardName="SomeStoryBoard" />
                    </DataTrigger.ExitActions>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Border.Style>
</Border>

答案 1 :(得分:1)

我的答案根据代码示例中的注释。

我已经从我的第一篇文章中删除了MultiDataTrigger,因为我无法使用绑定集合来实现这一点。我可能不得不问这个问题,看看是否有人对此问题有答案。

<Grid>
    <Grid.Resources>
            <!-- Don't use a ControlTemplate. This destroys your control structure, 
which doesn't make sense if all you want to do is animate the background. -->
            <Style x:Key="MyAnimatedFeatureStyle" TargetType="Button">
                <Style.Resources>
                    <RadialGradientBrush x:Key="GoldRadialGradientBrush">
                    <RadialGradientBrush.GradientStops>
                        <GradientStop Color="White" Offset="0" />
                        <GradientStop Color="Gold" Offset="1" />
                    </RadialGradientBrush.GradientStops>
                </RadialGradientBrush>
                <Storyboard RepeatBehavior="Forever" AutoReverse="False" x:Key="SomeStoryBoard">
                    <DoubleAnimation Storyboard.TargetProperty="Background.GradientStops[0].Offset" From="0" To="1" Duration="0:0:1" RepeatBehavior="Forever" AutoReverse="True" />
                </Storyboard>
            </Style.Resources>
            <Style.Triggers>
                <!-- Your primary binding condition. Whatever this may be. -->
                <DataTrigger Binding="{Binding Path=IsSOMTHINGSET}" Value="true" >
                    <!-- The Background is here in the setter, because we only want the background colored and animated on the binding condition. -->
                    <Setter Property="Background" Value="{StaticResource GoldRadialGradientBrush}" />
                    <DataTrigger.EnterActions>
                        <BeginStoryboard x:Name="BorderStoryBoard" Storyboard="{StaticResource SomeStoryBoard}" />
                    </DataTrigger.EnterActions>
                    <DataTrigger.ExitActions>
                        <RemoveStoryboard BeginStoryboardName="BorderStoryBoard" />
                    </DataTrigger.ExitActions>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Grid.Resources>

    <Button Style="{StaticResource MyAnimatedFeatureStyle}" />
</Grid>

答案 2 :(得分:0)

我实际上就像Charlie发布他的问题一样解决了这个问题。看起来我们想出了接近同样的事情。只是张贴我的参考:

<Button>
  <Button.Style>
    <Style TargetType="{x:Type Button}">
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate>
            <ControlTemplate.Resources>
              <RadialGradientBrush x:Key="GoldRadialGradientBrush">
                <RadialGradientBrush.GradientStops>
                  <GradientStop Color="White" Offset="0" />
                  <GradientStop Color="Gold" Offset="1" />
                </RadialGradientBrush.GradientStops>
              </RadialGradientBrush>
              <Storyboard x:Key="SomeStoryBoard">
                <DoubleAnimation
                  Storyboard.TargetProperty="(Border.Background).(GradientBrush.GradientStops)[0].Offset"
                  From="0" To="1" Duration="0:0:1"
                  RepeatBehavior="Forever"
                  AutoReverse="True" />
              </Storyboard>
            </ControlTemplate.Resources>
            <Grid>
              <Border Background="{StaticResource GoldRadialGradientBrush}">
                <Border.Style>
                  <Style TargetType="{x:Type Border}">
                    <Style.Triggers>
                      <DataTrigger Binding="{Binding Path=IsEnabled, RelativeSource={RelativeSource Self}}" Value="True">
                        <DataTrigger.EnterActions>
                          <BeginStoryboard x:Name="BorderStoryBoard" Storyboard="{StaticResource SomeStoryBoard}" />
                        </DataTrigger.EnterActions>
                        <DataTrigger.ExitActions>
                          <RemoveStoryboard BeginStoryboardName="BorderStoryBoard" />
                        </DataTrigger.ExitActions>
                      </DataTrigger>
                    </Style.Triggers>
                  </Style>
                </Border.Style>
              </Border>
            </Grid>
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>
  </Button.Style>
</Button>