WPF anchor Grid OpacityMask for Moving Grid Content

138 views Asked by At

I have a hexagonal Polygon that I am trying to use as an OpacityMask, then have content inside the polygon that can scroll and be clipped at the edges. The problem I encounter is that as the content moves, the OpacityMask moves with it (though by a different amount). Below is my code:

<Window Title="MainWindow" Height="450" Width="800">
    <Grid Height="450" Width="800">
        <StackPanel>
        <Grid ClipToBounds="True">
        <Grid.OpacityMask >
            <VisualBrush Stretch="None" >
                <VisualBrush.Visual>
                    <Polygon Points="220,225 310,69 490,69 580,225 490, 381 310, 381" Fill="Black" />
                </VisualBrush.Visual>
            </VisualBrush>
        </Grid.OpacityMask>
        <Polygon Points="220,225 310,69 490,69 580,225 490, 381 310, 381" Stroke="Black" StrokeThickness="5"/>
        <Rectangle x:Name="TestRectangle" Height="400" Width="400" Fill="Red" />
        </Grid>
            <Button Content="Testing" >
                <Button.Triggers>
                    <EventTrigger RoutedEvent="Button.Click">
                        <BeginStoryboard>
                            <Storyboard>
                                <ThicknessAnimation Storyboard.TargetName="TestRectangle" Storyboard.TargetProperty="Margin"
                                                    BeginTime="0:0:0" Duration="0:0:0.5" To="-400,0,0,0"/>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                </Button.Triggers>
            </Button>
        </StackPanel>
    </Grid>
</Window>

How do I anchor the opacity mask so that the grid content can move with the mask remaining stationary?

Edit: Answer Results and Additional Testing

Using the code in an answer provided, I still get movement of the hexagon:

Begin: Begin State End: End State

However, I have found that by adding a second rectangle that is transparent and that moves in the opposite direction of the red rectangle, I achieve the desired result. While this does work, it seems like there should be a better way to do it.

1

There are 1 answers

3
AbbasB On

If you try to set the margin of the rectangle directly, you would notice that it is ignored inside a grid. So one way to solve that would be to put the rectangle inside a border and animate the margin for that border

<Window x:Class="StackverflowTests.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:StackverflowTests"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800">
<Grid Height="450" Width="810">
    <StackPanel>
        <Grid ClipToBounds="True">
            <Grid.OpacityMask >
                <VisualBrush Stretch="None" >
                    <VisualBrush.Visual>
                        <Polygon Points="220,225 310,69 490,69 580,225 490, 381 310, 381" Fill="Black" />
                    </VisualBrush.Visual>
                </VisualBrush>
            </Grid.OpacityMask>
            <Polygon Points="220,225 310,69 490,69 580,225 490, 381 310, 381" Stroke="Black" StrokeThickness="5"/>
            <Border x:Name="TestRectangle">
                <Rectangle Height="400" Width="400" Fill="#ff0000"/>
            </Border>
        </Grid>
        <Button Content="Testing" >
            <Button.Triggers>
                <EventTrigger RoutedEvent="Button.Click">
                    <BeginStoryboard>
                        <Storyboard>
                            <ThicknessAnimation Storyboard.TargetName="TestRectangle" Storyboard.TargetProperty="Margin"
                                        BeginTime="0:0:0" Duration="0:0:0.5" To="-400,0,0,0" AutoReverse="True"/>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </Button.Triggers>
        </Button>
    </StackPanel>
</Grid>