Create After/Before Image slider control in WPF

Viewed 1253

I want to create a Before/After control like this https://codepen.io/dudleystorey/pen/HkwBo in WPF.

How to Stretch image at startup, and not stretch on splitter move, and made the same origin for two images.

<UserControl x:Class="BeforeAfterImage.BeforeAfterImageCtrl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="5" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <Image Stretch="None" Name="Before" Grid.Column="0" HorizontalAlignment="Left" Margin="0,0,0,0" VerticalAlignment="Top" />
    <GridSplitter Grid.Column="1" Width="5" HorizontalAlignment="Center" />
    <Image Stretch="None" Name="After" Grid.Column="2" HorizontalAlignment="Left" Margin="0,0,0,0" VerticalAlignment="Top" />
</Grid>

3 Answers

You could use a single-cell Grid to stack the two images on top of one another, then use a Slider control to adjust the width of the image that is "on top". (I used the same images as in your linked example, which are incidentally slightly different sizes; a bit odd given what the UI is trying to illustrate, but hey-ho).

<Window x:Class="WpfApplication2.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid HorizontalAlignment="Center" VerticalAlignment="Center">
        <Image x:Name="BeforeImage" HorizontalAlignment="Left"
            Source="https://s3-us-west-2.amazonaws.com/s.cdpn.io/4273/photoshop-face-before.jpg" />
        <Rectangle HorizontalAlignment="Left" Width="{Binding Value, ElementName=Slider}">
            <Rectangle.Fill>
                <ImageBrush ImageSource="https://s3-us-west-2.amazonaws.com/s.cdpn.io/4273/photoshop-face-after.jpg"
                    Stretch="UniformToFill" AlignmentX="Left" AlignmentY="Top" />
            </Rectangle.Fill>
        </Rectangle>
        <Slider x:Name="Slider" Maximum="{Binding ActualWidth, ElementName=BeforeImage}"
            VerticalAlignment="Bottom" Margin="0,0,0,40" />
    </Grid>
</Window>

Which looks like this when running:

Illustrative example

The only thing you'll probably want to do is style the Slider control to change its appearance to something more fitting. You should be able to find plenty of WPF control styling examples online.

Note that if the two images have different or non-standard DPIs then this technique probably won't work properly.

You may have the lower Image span all Grid columns, and bind the upper Image's Width and Height to the size of the lower one. However, everything is now left-aligned which might not be an issue of the UserControl is put into an appropriate container element.

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <Image x:Name="After" HorizontalAlignment="Left"
           Grid.ColumnSpan="3"
           Source="C:\Users\Public\Pictures\Sample Pictures\Koala.jpg"/>
    <Image x:Name="Before" HorizontalAlignment="Left"
           Width="{Binding ActualWidth, ElementName=After}"
           Height="{Binding ActualHeight, ElementName=After}"
           Source="C:\Users\Public\Pictures\Sample Pictures\Penguins.jpg"/>
    <GridSplitter Grid.Column="1" Width="5" HorizontalAlignment="Center"/>
</Grid>

I have done this before using a Canvas.

I had both images occupy the same space on the Canvas with the image on the left having a larger Z-Index than the image on the right so that it sits on top. Then put a slider in starting all the way left.

The only thing you need to do then is as the slider moves to the right, set the left images with to be the horizontal position of the slider.

Hope this helps

Related