zposten zposten - 3 months ago 25
C# Question

Clip UWP TextBlock as it moves out of its container

I'm attempting to build an odometer like effect in UWP where when a number is incremented it slides up and dissappears while the incremented number appears by sliding up from the bottom (in a very similar mannor to how the Odometer JS library works).

I have the number contained in a text block, that is animating properly.

<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)"
Storyboard.TargetName="Digit1">
<EasingDoubleKeyFrame KeyTime="0" Value="0" />
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="-80" />
</DoubleAnimationUsingKeyFrames>


Currently, when the number moves up it is still completely visible. I want the
TextBlock
to be "clipped" to its containing
Canvas
so that it progressively dissappears as it moves outside the bounds of the
Canvas
.

I have tried both clipping the
TextBlock
to the
Canvas
and visa versa, neither of which had the desired effect.

<Canvas x:Name="Odometer"
Clip="{Binding Clip, ElementName=Digit1}">
<TextBlock x:Name="Digit1"
FontSize="100"
Text="8"
Canvas.Left="-104"
Canvas.Top="-30"
RenderTransformOrigin="0.5,0.5"
Clip="{Binding Clip, ElementName=Odometer}">
<TextBlock.RenderTransform> <CompositeTransform /> </TextBlock.RenderTransform>
</TextBlock>
</Canvas>


I do not need to use a
Canvas
, it's just what I was playing around with. I'm still very new to UWP, so any help would be appreciated.

Answer

If you refer to UIElement.Clip:

The clipping geometry for UIElement.Clip in the Windows Runtime API must be a RectangleGeometry.

So, if you want to give a outline for canvas, you need to specify a RectangleGeometry for your canvas.clip, which take a rect of your canvas's actual size.

You can achieve this progrmmatically:

private void Odometer_Loaded(object sender, RoutedEventArgs e)
{
    RectangleGeometry rectangle = new RectangleGeometry();
    rectangle.Rect = new Rect(0, 0, Odometer.ActualWidth, Odometer.ActualHeight);
    Odometer.Clip = rectangle;
}

And don't forget to remove the clip in xaml:

<Canvas x:Name="Odometer" Loaded="Odometer_Loaded">
        <TextBlock x:Name="Digit1"
           FontSize="100"
           Text="8"
           Canvas.Left="104"
           Canvas.Top="10"
           RenderTransformOrigin="0.5,0.5">
                <TextBlock.RenderTransform>
                    <CompositeTransform />
                </TextBlock.RenderTransform>
        </TextBlock>
</Canvas>