Search code examples
c#wpfxamlstoryboardeventtrigger

Reverse Triggered Animation If Method Fails Using Xaml, Not Code Behind


I have a login form with a button (btnLogin). When a user clicks btnLogin, the following Storyboard is triggered to disable btnLogin, txtUsername, pbPassword ...

<EventTrigger RoutedEvent="Button.Click">
    <EventTrigger.Actions>
        <BeginStoryboard>
            <Storyboard>
                <BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="IsEnabled" FillBehavior="HoldEnd">
                    <DiscreteBooleanKeyFrame KeyTime="00:00:00" Value="False" />
                </BooleanAnimationUsingKeyFrames>
                <BooleanAnimationUsingKeyFrames Storyboard.TargetName="txtUsername" Storyboard.TargetProperty="IsEnabled" FillBehavior="HoldEnd">
                    <DiscreteBooleanKeyFrame KeyTime="00:00:00" Value="False" />
                </BooleanAnimationUsingKeyFrames>
                <BooleanAnimationUsingKeyFrames Storyboard.TargetName="pbPassword" Storyboard.TargetProperty="IsEnabled" FillBehavior="HoldEnd">
                    <DiscreteBooleanKeyFrame KeyTime="00:00:00" Value="False" />
                </BooleanAnimationUsingKeyFrames>
            </Storyboard>
        </BeginStoryboard>
    </EventTrigger.Actions>
</EventTrigger>

... as this Storyboard runs, the Button.Click event is also attached to a btnLogin_Click method which verifies the users credentials. Fair enough!

Currently, if the login attempt fails, I have to use the following (dirty?!) code in btnLogin_Click to re-enable the btnLogin, txtUsername, pbPassword controls so the details can be re-entered ...

btnLogin.Triggers.Clear();
btnLogin.BeginAnimation(UIElement.IsEnabledProperty, null);
txtUsername.BeginAnimation(UIElement.IsEnabledProperty, null);
pbPassword.BeginAnimation(UIElement.IsEnabledProperty, null);

Can i handle this re-enabling using Xaml instead? I'm sure I can, I just can't figure out how to do it?!

Thanks for your help :O)


UPDATE

I've tried using EnterActions and ExitActions as suggested by bars222, but this approach has no means to determine if the btnLogin_Click event resulted in a successful or unsuccessful login.


Solution

  • If I clearly understand, you want to set IsEnabled to true after the login attempt. In that case you can use EventTrigger.EnterActions and EventTrigger.ExitActions triggers. Here some example.

    <EventTrigger RoutedEvent="Button.Click">
        <EventTrigger.EnterActions>
            <BeginStoryboard>
                <Storyboard>
                    <BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="IsEnabled" FillBehavior="HoldEnd">
                        <DiscreteBooleanKeyFrame KeyTime="00:00:00" Value="False" />
                    </BooleanAnimationUsingKeyFrames>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger.EnterActions>
        <EventTrigger.ExitActions>
            <BeginStoryboard>
                <Storyboard>
                    <BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="IsEnabled" FillBehavior="HoldEnd">
                        <DiscreteBooleanKeyFrame KeyTime="00:00:00" Value="True" />
                    </BooleanAnimationUsingKeyFrames>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger.ExitActions>
    </EventTrigger>
    

    Update

    Solution with data binding. You can create some property, that indicates authorization process. You should update this during auth process.

    private bool _isAuth;
    public bool IsAuth
    {
        get { return _isAuth; }
        set { _isAuth = value; NotifyPropertyChanged( "IsAuth" ); }
    }
    
    #region INotifyPropertyChanged Members
    public event PropertyChangedEventHandler PropertyChanged;
    #endregion
    protected void NotifyPropertyChanged( String info )
    {
        if ( PropertyChanged != null )
        {
            PropertyChanged( this, new PropertyChangedEventArgs( info ) );
        }
    }
    

    You should set DataContext of these elements. For example, if you created property in authorization window. You can write in constructor.

    this.DataContext = this;
    

    And bind it to your elements to enable/disable it.

    <Button Click="Button_Click" IsEnabled="{Binding IsAuth}" />