Zum Inhalt
Kuonen.UI

LayoutTransformControl

Das LayoutTransformControl dreht, skaliert oder schert sein Kind schon im Layout: Die Nachbarn rücken zur Seite, weil die transformierte Fläche ihren Platz bekommt. Die RenderTransform dagegen verändert nur die Darstellung und nimmt keinen Platz. Drehen Sie den Regler und vergleichen Sie die Spalten. Eine feste Drehung steht im KXAML als Matrix LayoutTransform="0.7071,0.7071,-0.7071,0.7071,0,0".

Vorführung: LayoutTransformControlVorführung: LayoutTransformControl

KXAML

LayoutTransformSeite.kxaml
<StackPanel xmlns="https://ui.kuonen.org/kxaml"
            xmlns:x="https://ui.kuonen.org/kxaml/x"
            x:Class="Kuonen.UI.Galerie.Seiten.LayoutTransformVorfuehrung"
            Spacing="8">
  <TextBlock x:Name="Winkel" Text="Drehwinkel: 30°" />
  <Slider Minimum="0" Maximum="360" Value="30" SmallChange="1" LargeChange="15" Width="300" HorizontalAlignment="Left" ValueChanged="Winkel_ValueChanged" />
  <StackPanel Orientation="Horizontal" Spacing="8">
    <Border Width="190" BorderBrush="#A0A0A0" BorderThickness="1" Padding="8">
      <StackPanel Spacing="4">
        <TextBlock Text="LayoutTransform" FontWeight="SemiBold" />
        <TextBlock Text="Davor" />
        <LayoutTransformControl x:Name="Layout" HorizontalAlignment="Left">
          <Button Content="Gedreht" Width="120" Height="32" />
        </LayoutTransformControl>
        <TextBlock Text="Danach" />
      </StackPanel>
    </Border>
    <Border Width="190" BorderBrush="#A0A0A0" BorderThickness="1" Padding="8">
      <StackPanel Spacing="4">
        <TextBlock Text="RenderTransform" FontWeight="SemiBold" />
        <TextBlock Text="Davor" />
        <Button x:Name="Render" Content="Gedreht" Width="120" Height="32" HorizontalAlignment="Left" />
        <TextBlock Text="Danach" />
      </StackPanel>
    </Border>
    <Border Width="190" BorderBrush="#A0A0A0" BorderThickness="1" Padding="8">
      <StackPanel Spacing="4">
        <TextBlock Text="Fest, 45°" FontWeight="SemiBold" />
        <TextBlock Text="Davor" />
        <LayoutTransformControl LayoutTransform="0.7071,0.7071,-0.7071,0.7071,0,0" HorizontalAlignment="Left">
          <Button Content="45°" Width="120" Height="32" />
        </LayoutTransformControl>
        <TextBlock Text="Danach" />
      </StackPanel>
    </Border>
  </StackPanel>
</StackPanel>
LayoutTransformSeite.kxaml.cs
using Kuonen.UI;
using Kuonen.UI.Controls;
using Kuonen.UI.Media;

namespace Kuonen.UI.Galerie.Seiten;

public sealed partial class LayoutTransformSeite
{
    protected override Func<UIElement>? KxamlFabrik => () => new LayoutTransformVorfuehrung();
}

/// <summary>KXAML-Fassung der Seite zum LayoutTransformControl: der Baum steht in LayoutTransformSeite.kxaml, hier nur das Verhalten.</summary>
public sealed partial class LayoutTransformVorfuehrung
{
    private const double KnopfBreite = 120, KnopfHoehe = 32;

    public LayoutTransformVorfuehrung()
    {
        InitializeComponent();
        Render.RenderTransform = UmMitte(30);
        Layout.LayoutTransform = Matrix.CreateRotation(30);
    }

    /// <summary>Drehung um die Mitte des Knopfs (die RenderTransform hat keinen eigenen Mittelpunkt).</summary>
    private static Matrix UmMitte(double grad) =>
        Matrix.CreateTranslation(-KnopfBreite / 2, -KnopfHoehe / 2) * Matrix.CreateRotation(grad) * Matrix.CreateTranslation(KnopfBreite / 2, KnopfHoehe / 2);

    private void Winkel_ValueChanged(object? sender, WertGeaendertArgs e)
    {
        double grad = Math.Round(e.Neu);
        Winkel.Text = $"Drehwinkel: {grad}°";
        Layout.LayoutTransform = Matrix.CreateRotation(grad);
        Render.RenderTransform = UmMitte(grad);
    }
}

C#

LayoutTransformSeite.cs
using Kuonen.UI;
using Kuonen.UI.Controls;
using Kuonen.UI.Layout;
using Kuonen.UI.Media;

namespace Kuonen.UI.Galerie.Seiten;

/// <summary>Galerie-Seite: <see cref="LayoutTransformControl"/>.</summary>
public sealed partial class LayoutTransformSeite : GalerieSeite
{
    public override string Titel => "LayoutTransformControl";

    public override string Beschreibung =>
        "Das LayoutTransformControl dreht, skaliert oder schert sein Kind schon im Layout: Die Nachbarn rücken zur Seite, weil die "
        + "transformierte Fläche ihren Platz bekommt. Die RenderTransform dagegen verändert nur die Darstellung und nimmt keinen "
        + "Platz. Drehen Sie den Regler und vergleichen Sie die Spalten. Eine feste Drehung steht im KXAML als Matrix "
        + "LayoutTransform=\"0.7071,0.7071,-0.7071,0.7071,0,0\".";

    public override string Stichworte => "LayoutTransform LayoutTransformControl drehen Drehung Rotation RenderTransform Matrix transformieren schräg";

    public override string Datei => nameof(LayoutTransformSeite);

    private const double KnopfBreite = 120, KnopfHoehe = 32;

    private static readonly SolidColorBrush Rand = new(Color.FromRgb(160, 160, 160));

    /// <summary>Drehung um die Mitte des Knopfs (die RenderTransform hat keinen eigenen Mittelpunkt).</summary>
    private static Matrix UmMitte(double grad) =>
        Matrix.CreateTranslation(-KnopfBreite / 2, -KnopfHoehe / 2) * Matrix.CreateRotation(grad) * Matrix.CreateTranslation(KnopfBreite / 2, KnopfHoehe / 2);

    private static Border Spalte(string titel, UIElement mitte)
    {
        var spalte = new StackPanel { Spacing = 4 };
        spalte.Children.Add(new TextBlock { Text = titel, FontWeight = 600 });
        spalte.Children.Add(new TextBlock { Text = "Davor" });
        spalte.Children.Add(mitte);
        spalte.Children.Add(new TextBlock { Text = "Danach" });
        return new Border { Width = 190, BorderBrush = Rand, BorderThickness = new Thickness(1), Padding = new Thickness(8), Child = spalte };
    }

    public override UIElement Baue()
    {
        var winkel = new TextBlock { Text = "Drehwinkel: 30°" };
        var regler = new Slider { Minimum = 0, Maximum = 360, Value = 30, SmallChange = 1, LargeChange = 15, Width = 300, HorizontalAlignment = HorizontalAlignment.Left };

        var layoutKnopf = new Button { Content = "Gedreht", Width = KnopfBreite, Height = KnopfHoehe };
        var layout = new LayoutTransformControl { Child = layoutKnopf, LayoutTransform = Matrix.CreateRotation(30), HorizontalAlignment = HorizontalAlignment.Left };

        var renderKnopf = new Button { Content = "Gedreht", Width = KnopfBreite, Height = KnopfHoehe, RenderTransform = UmMitte(30), HorizontalAlignment = HorizontalAlignment.Left };

        var fest = new LayoutTransformControl
        {
            Child = new Button { Content = "45°", Width = KnopfBreite, Height = KnopfHoehe },
            LayoutTransform = new Matrix(0.7071, 0.7071, -0.7071, 0.7071, 0, 0),
            HorizontalAlignment = HorizontalAlignment.Left,
        };

        regler.ValueChanged += (_, e) =>
        {
            double grad = Math.Round(e.Neu);
            winkel.Text = $"Drehwinkel: {grad}°";
            layout.LayoutTransform = Matrix.CreateRotation(grad);
            renderKnopf.RenderTransform = UmMitte(grad);
        };

        var spalten = new StackPanel { Orientation = Orientation.Horizontal, Spacing = 8 };
        spalten.Children.Add(Spalte("LayoutTransform", layout));
        spalten.Children.Add(Spalte("RenderTransform", renderKnopf));
        spalten.Children.Add(Spalte("Fest, 45°", fest));

        var seite = new StackPanel { Spacing = 8 };
        seite.Children.Add(winkel);
        seite.Children.Add(regler);
        seite.Children.Add(spalten);
        return seite;
    }
}