wpfdatagridwpf-controlswpf-animation

WPF Source Name property cannot be set within Style. Triggers section Error


I'm getting an error with the following details:

Source Name property cannot be set within Style. Triggers section

        <Rectangle Margin="121,163,0,248" HorizontalAlignment="Left" Width="33" Height="34">
            <Rectangle.Style>
                <Style TargetType="Rectangle">
                    <Setter Property="Fill" Value="Blue"></Setter>
                    <Style.Triggers>
                        <EventTrigger SourceName="myButton"  RoutedEvent="Button.Click">
                            <BeginStoryboard>
                                <Storyboard>
                                    <ColorAnimation 
                                        Storyboard.TargetProperty="Fill.Color" To="Orange" 
                                        Duration="0:0:1" AutoReverse="True" RepeatBehavior="Forever"
                                        BeginTime="0:0:0">
                                    </ColorAnimation>
                                </Storyboard>
                            </BeginStoryboard>
                        </EventTrigger>
                    </Style.Triggers>
                </Style>
            </Rectangle.Style>

I want to change the rectangle fill color with Color Animation tag when click on button.


Solution

  • Like it says, you cannot use source name in a style like that.

    You can use a data trigger instead. Set say a bool property in your viewmodel from your button's command of click.

    Then start your storyboard with a datatrigger binding that bool property and comparing value.

    You can probably easily Google datatrigger and storyboard but here's a so question includes an example.

    WPF Data Triggers and Story Boards

    Btw.

    Routed events are rarely very useful IME. Binding icommand is way more practical. Usually.

    Edit:

    Here's a quick and dirty sample using a togglebutton. Since this approach uses binding it can reference controls by name. Binding is resolved at run time.

        <Grid>
        <Rectangle>
            <Rectangle.Style>
                <Style TargetType="Rectangle">
                    <Setter Property="Fill" Value="Blue"></Setter>
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding IsChecked, ElementName=StartStop}" Value="True">
                            <DataTrigger.EnterActions>
                                <BeginStoryboard  x:Name="ColourStoryboard">
                                    <Storyboard>
                                        <ColorAnimation 
                                            Storyboard.TargetProperty="Fill.Color" To="Orange" 
                                            Duration="0:0:1" AutoReverse="True" RepeatBehavior="Forever"
                                             >
                                        </ColorAnimation>
                                    </Storyboard>
                                </BeginStoryboard>
                            </DataTrigger.EnterActions>
                            <DataTrigger.ExitActions>
                                <StopStoryboard  BeginStoryboardName="ColourStoryboard"/>
                            </DataTrigger.ExitActions>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </Rectangle.Style>
        </Rectangle>
        <ToggleButton Content="Start Stop" 
                      HorizontalAlignment="Left"
                      VerticalAlignment="Top"
                      Name="StartStop"/>
    </Grid>
    </Window>
    

    Paste the grid inside a mainwindow, spin it up. When you click the togglebutton it sets ischecked true so the rectangle animates to orange and back to blue. When you click the button again, ischecked becomes false and the animation stops.

    You could instead write code in a button handler that set a bound property which is in the datacontext and bind the datatrigger to that bound property. That's what the markup in the link is doing with IsBusy.