2

I'm trying to learn about attached behaviors in WPF/WP7 Silverlight, and I've come up against a conceptual roadblock that I wondered if someone could weigh in on.

An example of the functionality I'm trying to create is the following: The user clicks on a button whose Click handler triggers navigation (i.e. NavigationContext.Navigate()), and prior to the navigation actually occurring, an animation occurs on the button that reduces its opacity from 1 to 0 (a "fade out" effect).

So, in order:

  1. The user clicks the button
  2. The button executes an animation
  3. The navigation occurs

Simple enough, right? I created an attached behavior that looks like so:

public class FadeBehavior : Behavior<Button>
{
    protected override void OnAttached()
    {
        base.OnAttached();

        AssociatedObject.Click += (obj, args) => {
            Storyboard sb = new Storyboard();

            DoubleAnimation an = new DoubleAnimation();
            an.Duration = TimeSpan.FromMilliseconds(300);
            an.From = 1;
            an.To = 0;
            Storyboard.SetTarget(an, AssociatedObject);
            Storyboard.SetTargetProperty(an, new PropertyPath("Opacity"));

            sb.Children.Add(an);
            sb.Begin();
        };
    }
}

This obviously works fine if the .xaml.cs of the page the button's on doesn't contain a Click handler that triggers navigation, but when I wire that up, the animation doesn't complete before the navigation occurs. I understand why this is, of course, but I'm wondering if there's a method to accomplish this that also exhibits the wonderful property of non-terrible design.

I found this SO thread that is seemingly related, but is the accepted answer REALLY the only way to do this?

Thanks for your help.

EDIT: If you happen to have a WP7 and are hell-bent on figuring this out, the Reddit reader app "Baconit" exhibits a behavior similar to the one I'm interested in when you click on the title of a story.

Community
  • 1
  • 1
Jammer
  • 441
  • 5
  • 15
  • Don't know if you consider it as terrible design, but i would always attach a handler to the [Completed](http://msdn.microsoft.com/en-us/library/system.windows.media.animation.timeline.completed.aspx) event of a Storyboard or Animation to do something when it has finished. – Clemens Feb 10 '12 at 18:50
  • Good call, and that idea did occur to me. I'm no design expert, but my thought was that Behaviors are really designed to do stuff like this - I was just hoping there'd be a way to do it without requiring that the page's .xaml.cs know anything about the animation storyboard. But that may be what I end up doing :-) Thanks! – Jammer Feb 10 '12 at 18:52
  • Maybe you could create your own version of the [NavigateToPageAction](http://msdn.microsoft.com/en-us/library/ff979325(v=expression.40).aspx) behavior. Then you could use the Completed event, and navigate to the specified page all within the behavior. I have not tried that, though. I guess using the click event in xaml.cs would still cause a problem. – Paul Hoenecke Feb 10 '12 at 20:55

1 Answers1

0

If you are creating attached behaviours I am assuming you are aiming to eliminate code behind? However, you want to add a click handler to the button, which will result in code behind? There seems to be a conflict here!

I see two options ...

If you are happy with code behind, forget about attached behaviors! Just create a utility class that executes an animation then invokes a delegate on completion. You can then use this wherever you want to apply this effect.

If you want to eliminate code behind you should be using commands rather than click handlers. Add an ICommand property to your attached behavior which is executed when your storyboard completes. You can then bind this to a command exposed your view model.

See thus question which shows how binding is possible with blend behavior properties:

Blend Behaviours - can you bind to their properties?

Community
  • 1
  • 1
ColinE
  • 68,894
  • 15
  • 164
  • 232