Let’s build a sleek way to display notifications to the user. The messages won’t show up in traditional pop-up windows, but instead slide in at the top of the screen. User can dismiss each one of them by clicking at it.
Complete project is available on GitHub and this blog post covers only bits related to animation.
Each message animates twice: first, when it’s added to the collection and first rendered, and second time, disappearing after user dismissed it.
The DataTrigger fires the animation whenever property IsAlive is found to be true. Here, we instantiate it to true in each MessageObject.
Let’s see how it looks like:
The slide-out effect for removed messages gets a bit more tricky. Once the element is removed from the collection, we can’t animate it, because its graphical representation disappears.
We will use the property IsAlive to trigger the slide-out animation, and we will actually remove the message from the collection after the animation completes. Similarly to the enter animation, the exit animation is triggered by setting isAlive to false. This can be defined twofold in XAML:
Ideally, we would listen to StoryboardCompleted event and remove the item once the framework tell us that the animation has completed. However, the StoryboardCompleted event doesn’t have a reference to the removed item or the collection. How would we know which item to remove from the collection?
We need to wait agreed amount of time in the code-behind before the element can be removed from the collection. This is not an ideal solution, but I can’t think of another way to achieve this.
Here’s how it looks like:
We can see the item occupies its space as it animates out, and other items abruptly jump in its space after the item is removed.
We can address that by adding a slide-up animation to the exitStoryboard. The second animation starts only when the first animation ends (note the BeginTime). The animation changes the top margin of the item to -50, effectively dragging it up. We’re happy to see that all items below it also move up!
Now we only need to change the code-behind to wait for both animations to finish before removing the element, so we change the delay from 250ms to 500ms. That’s the final effect:
For best results, this control can be placed above the rest of your app with help of Z-index