3

In a WPF project, I have an ItemsControl bound to a collection of the ViewModel. It's ItemTemplate contains an Image control bound to property of the object collection. I have a timer which fetches new images every minute from a JSON service and assigns them to that property bound to the Image.

What I wanna do is trigger a simple animation when that property changes. Particularly, I want to trigger a simple fade-out animation right before the new image is assigned to my property, that would involve the PropertyChanging event, and a fade-in animation on PropertyChanged so I would have a smooth transition from the old to new image in my View.

I've tried the following taken from another question but that triggers the animation after the property changes which isn't what I want:

<Image 
    x:Name="ChannelImage"
    Width="230" Height="230" 
    Source="{Binding ImageByteArray, Converter={StaticResource ByteArrayToBitmapImageConverter}, 
                                     NotifyOnTargetUpdated=True}">
    <Image.Triggers>
        <EventTrigger RoutedEvent="Binding.TargetUpdated">
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimation 
                        Storyboard.TargetName="ChannelImage"
                        Storyboard.TargetProperty="Opacity"
                        BeginTime="0:0:0"
                        Duration="0:0:1"
                        To="0"/>
                    <DoubleAnimation 
                        Storyboard.TargetName="ChannelImage"
                        Storyboard.TargetProperty="Opacity"
                        BeginTime="0:0:2"
                        Duration="0:0:1"
                        To="1"/>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Image.Triggers>
</Image>

Any help would be much appreciated.

Community
  • 1
  • 1
Pantelis
  • 2,060
  • 3
  • 25
  • 40

1 Answers1

4

It is not that easy to fade out the old image and fade in a new one. In your situation, I would do the following to maintain a good separation of concerns:

  1. Fetch the image from the uri and create a new Image in code. If you need further info on that, have a look at this question on Stack Overflow.
  2. If you want to apply MVVM, you should perform step 1 in a view model and set the corresponding property that raises PropertyChanged. Otherwise just update the corresponding control that I mention in step 3 manually.
  3. Implement a custom ContentControl that actually does the heavy lifting: when its Content property changes, it fades out the old content and fades in the new one. This is the hardest part, but if you introduce this new control, you can write your view models the same way as before and leave all the fading stuff to this new control.

I've implemented a small project for you that you can download via this Dropbox link (requires .NET 4.5). I created the class AnimatedContentControl which is a WPF Custom Control that has two Content Presenters inside its default Control Template. When the Content property is set on this control, the old content gets assigned to the OldContent Dependency Property which is faded out. Afterwards, the new content is then faded in. All this is done using the storyboard FadeInFromRight that is part of the control templates' resources. This storyboard is started in the overriden method OnContentChanged in AnimatedContentControl.cs.

The other classes are just the MainWindow and the MainWindowViewModel which use the default MVVM pattern.

If you have any questions, please feel free to ask. I hope I could help you with this problem.

Community
  • 1
  • 1
feO2x
  • 5,358
  • 2
  • 37
  • 46
  • Thank you very much for taking the time to create a sample project man. I probably wouldn't come up with such a solution as my custom Control skills are not that great. I'll see how I can incorporate this to my project and report back. – Pantelis Aug 15 '14 at 14:39
  • 1
    If you want to, you can copy `AnimatedContentControl.cs`, `IStoryboardFinder.cs`, `ResourceDictionaryStoryboardFinder.cs`, `AnimatedContentControlDefaultStyle.xaml`and `Generic.xaml` to your project. Both xaml files have to be located in a folder called `Themes` within your project. Afterwards, you can just bind the content property as I've done in `MainWindow.xaml`. – feO2x Aug 15 '14 at 14:49
  • 1
    +1 for custom control since it makes the animation reusable by just plug in simple Views and ViewModels. – Rohit Vats Aug 15 '14 at 15:31
  • This is just epic. What you did is pretty complex, but it works great and you can literally copy and paste it in your project and it will work. I'm using it to present status text and it really adds that extra polish to my app. – Ebsan May 10 '15 at 04:52
  • 1
    If you're using this to present your own custom controls (control inside a control) you might want to increase the keytimes. I had to increase the keytimes to make larger controls ease in and out smoothly. – Ebsan May 10 '15 at 05:08