Search code examples
wpfribbon

Image transition animation on ribbon button


How can I create a WPF ribbon button switching between two images, with an animated "wipe" transition between images? I can't place both images within a a grid within the button and animate the opacity of each image in turn (as suggested here) because I can't set the content of the ribbon directly, only the LargeImageSource/SmallImageSource and Label properties.

Update

I tried BorisB.'s suggestion together with the animation from the link above, but there is now no image displayed in the ribbon button. Removing the animation, opacity mask and multiple images, and leaving the following code also doesn't show the image at all.

<RibbonToggleButton Label="Dashboard" Name="btnDashboard" IsChecked="True">
  <RibbonToggleButton.LargeImageSource>
    <DrawingImage>
      <DrawingImage.Drawing>
        <DrawingGroup>
          <ImageDrawing ImageSource="/Icons/Dashboard.png" />
        </DrawingGroup>
      </DrawingImage.Drawing>
    </DrawingImage>
  </RibbonToggleButton.LargeImageSource>
</RibbonToggleButton>

Solution

  • You can use a DrawingImage as an ImageSource. Then you can assign a DrawingGroup as a DrawingImage.Drawing. That drawing group can contain two ImageDrawings wrapped in their own DrawingGroups, so you could apply the approach from your link:

    <Grid>
        <Ribbon>
            <RibbonTab x:Name="HomeTab" Header="Home">
                <RibbonGroup x:Name="Group1" Header="Group1">
                    <RibbonButton x:Name="Button1" Label="Button1">
                        <RibbonButton.LargeImageSource>
                            <DrawingImage>
                                <DrawingImage.Drawing>
                                    <DrawingGroup>
                                        <DrawingGroup>
                                            <ImageDrawing Rect="0, 0, 32, 32" ImageSource=ImageOne.png"/>
                                        </DrawingGroup>
                                        <DrawingGroup>
                                            <ImageDrawing Rect="0, 0, 32, 32" ImageSource="ImageTwo.png"/>
                                            <DrawingGroup.OpacityMask>
                                                <LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
                                                    <GradientStop Offset="0" Color="Black" x:Name="BlackStop"/>
                                                    <GradientStop Offset="0" Color="Transparent" x:Name="TransparentStop"/>
                                                </LinearGradientBrush>
                                            </DrawingGroup.OpacityMask>
                                        </DrawingGroup>
                                    </DrawingGroup>
                                </DrawingImage.Drawing>
                            </DrawingImage>
                        </RibbonButton.LargeImageSource>
                    </RibbonButton>
                </RibbonGroup>
            </RibbonTab>
        </Ribbon>
    </Grid>
    <Window.Triggers>
        <EventTrigger RoutedEvent="Window.Loaded">
            <EventTrigger.Actions>
                <BeginStoryboard>
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetName="TransparentStop" 
                             Storyboard.TargetProperty="Offset" By="1"  Duration="0:0:2"   />
                        <DoubleAnimation Storyboard.TargetName="BlackStop" 
                             Storyboard.TargetProperty="Offset" By="1" Duration="0:0:2" 
                             BeginTime="0:0:0.05" />
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger.Actions>
        </EventTrigger>
    </Window.Triggers>
    

    The wrapping DrawingGroups are used so you can use OpacityMask, which is essential for the effect.