In my .NET 4.8 WPF application I have a window with two ContainerVisual
elements:
_rootContainerVisual
_containerVisualToRotate
-
child of
_rootContainerVisual
-
displays multiple images on multiple sprites that are position next to each other in a certain way in the real application.
-
displays a fill brush in the provided example code.
-
The content is bigger than the size of both
ContainerVisual
I would like to rotate the complete _containerVisualToRotate around the z-axis.
-
When I do this I notice that part of the images/brush inside the _containerVisualToRotate is clipped, although there is enough space.
In standard WPF I used a negative margin to make it work.
Example xaml (no code behind required):
<Window x:Class="PlayingAroundInWpf.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:PlayingAroundInWpf"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800" MouseEnter="Window_MouseEnter" MouseLeave="Window_MouseLeave">
<Grid Background="AntiqueWhite">
<Grid x:Name="mainGrid" RenderTransformOrigin="0.5,0.5" Margin="-100">
<Grid.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform Angle="15"/>
<TranslateTransform/>
</TransformGroup>
</Grid.RenderTransform>
<Rectangle Fill="LightBlue" Opacity="0.2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
<Label HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="72">Test with standard WPF</Label>
</Grid>
</Grid>
</Window>
This leads to the following: the inner content is bigger then the visible part of the view -> the inner content is not getting clipped during rotation.
I tried to do something similar with the _containerVisualToRotate
by
-
using the Clip property with negative numbers.
-
setting the Size property of the _containerVisualToRotate to a high number
-
settting the RelativeSizeAdjustment to values >5.0f
-
setting the Size property of the rectangle to a high number
However, none of this leads to the desired result.
Here is my example code behind (the xaml is actually an empty window):
public partial class ContainerVisualExample : Window
{
private IntPtr _hwndHost;
private Windows.UI.Composition.Compositor _compositor;
private Windows.UI.Composition.CompositionTarget _target;
private Windows.UI.Composition.ContainerVisual _rootContainerVisual;
private Windows.UI.Composition.ContainerVisual _containerVisualToRotate;
public ContainerVisualExample()
{
InitializeComponent();
Loaded += ContainerVisualExample_Loaded;
}
private void ContainerVisualExample_Loaded(object sender, RoutedEventArgs e)
{
SetupCompositions();
AddRectangleToContainer();
RotateContainerVisual();
}
private void SetupCompositions()
{
_hwndHost = new System.Windows.Interop.WindowInteropHelper(this).Handle;
_compositor = new Compositor();
_target = _compositor.CreateDesktopWindowTarget(_hwndHost, false);
// Setup the _rootContainerVisual.
_rootContainerVisual = _compositor.CreateContainerVisual();
_rootContainerVisual.RelativeSizeAdjustment = Vector2.One;
_rootContainerVisual.Offset = new Vector3(0, 0, 0);
_containerVisualToRotate = _compositor.CreateContainerVisual();
_containerVisualToRotate.RelativeSizeAdjustment = new Vector2(5.0f, 5.5f);
_containerVisualToRotate.Offset = new Vector3(0, 0, 0);
_containerVisualToRotate.Size = new Vector2(10000, 10000);
_containerVisualToRotate.Clip = _compositor.CreateInsetClip(-10000, -10000, -10000, -10000);
_containerVisualToRotate.CenterPoint = new Vector3(400, 225, 0);
_rootContainerVisual.Children.InsertAtTop(_containerVisualToRotate);
_target.Root = _rootContainerVisual;
}
private void AddRectangleToContainer()
{
// Create a rectangle element
Windows.UI.Composition.SpriteVisual rectangleVisual = _compositor.CreateSpriteVisual();
rectangleVisual.Size = new Vector2(10000, 10000);
// Set the fill color of the rectangle to light blue
Windows.UI.Color lightBlueColor = Windows.UI.Color.FromArgb(255, 173, 216, 230);
Windows.UI.Composition.CompositionColorBrush fillBrush = _compositor.CreateColorBrush(lightBlueColor);
rectangleVisual.Brush = fillBrush;
// Add the rectangle to the _containerVisualToRotate
_containerVisualToRotate.Children.InsertAtTop(rectangleVisual);
}
private void RotateContainerVisual()
{
_containerVisualToRotate.RotationAngleInDegrees = 45.0f;
}
}
However, this still leads to clipping:
Now, I’m out of ideas on how to get this working.
As I wrote above: rotating the inner content (in the example the rectangle) is not really an option, since it contains several sprites that would all need to be rotated individually around the same center point.
Is there any other way?