Dziś będzie ciekawy (przynajmniej dla mnie) temat. Transformacje.

WPF wprowadza możliwość zastosowania transformacji na kontrolkach. Wyróżniamy dwa rodzaje transformacji: LayoutTransform oraz RenderTransform. LayoutTransform jest stosowany przed tym jak kontrolka zostanie rozmieszczona. Drugi tj. RenderTransform po, ale przed tym jak ma zostać ona narysowana. Poniższy rysunek powinien wszystko wyjaśnić.

    <Button Content=”Przycisk 1″

          Background=”Orange”>

        <Button.LayoutTransform>

            <ScaleTransform CenterX=”.5″ CenterY=”.5″ ScaleY=”2″ />

        Button.LayoutTransform>

    Button>

    <Button Content=”Przycisk 2″

          Background=”Red”>

    Button>

    <Button Content=”Przycisk 3″

          Background=”Orange”>

        <Button.RenderTransform>

            <ScaleTransform CenterX=”.5″ CenterY=”.5″ ScaleY=”2″ />

        Button.RenderTransform>

    Button>

    <Button Content=”Przycisk 4″

          Background=”Red”>

    Button>

StackPanel>

Widzimy, że przycisk 1 jest całkowicie widoczny w odróżnieniu od przycisku 3, który został przysłonięty przez ostatni. Zanim przejdziemy do omówienia poszczególnych transformacji warto jeszcze wspomnieć, że punktem centralnym transformacji możemy sterować za pomocą właściwości RenderTransformOrigin

<Button Content=”Przycisk 3″

      Background=”Orange” RenderTransformOrigin=”1,0″>

    <Button.RenderTransform>

        <ScaleTransform  ScaleY=”2″ ScaleX=”2″ />

    Button.RenderTransform>

Button>

<Button Content=”Przycisk 4″

      Background=”Red”>

Button>

Obroty

Umożliwiają obrócenie kontrolki o zadany kąt (w stopniach). Najistotniejszy jest fakt, że kontrolka po obrocie nadal jest w pełni funkcjonalna. No może trochę trudniej się jej używa. Przykład:

<GroupBox Header=”Wybór”>

    <GroupBox.LayoutTransform>

        <RotateTransform Angle=”45″ />

    GroupBox.LayoutTransform>

    <StackPanel>

        <RadioButton Content=”Opcja 1″ />

        <RadioButton Content=”Opcja 2″ />

        <RadioButton Content=”Opcja 3″ />

    StackPanel>

GroupBox>

Dodatkowo możemy określić punkt środkowy obrotu za pomocą właściwości CenterX, CenterY. Wartości z przedziału 0-1 (obustronnie domknięty przedział).

Skalowanie

To rozciąganie elementu w pionie i/lub poziomie. Wystarczy dodać taki kod:

<ScaleTransform ScaleX=”1″ ScaleY=”2″ />

Przekrzywienie

To ciekawa transformacja pozwalająca uzyskać “ciekawe” wizualnie efekty. Możemy przekrzywiać oddzielnie względem osi X i Y. Zastosowanie

<SkewTransform AngleX=”15″ AngleY=”11″ />

na przycisku da nam następujący efekt końcowy

A przycisk oczywiście nadal jest klikalny.

Translacja

Ta transformacja ma widoczny efekt tylko dla RenderTransform i objawia się przesunięciem kontrolki o zadany wektor. Użycie jest proste:

<TranslateTransform X=”20″ Y=”10″ />

Transformacja macierzowa

Jeśli ktoś jest zaznajomiony z podstawami algebry, to wszystkie powyższe transformacji (i ich kombinacje) może uzyskać za pomocą tej.

Definiujemy ją w poniższy sposób:

<MatrixTransform>

    <MatrixTransform.Matrix>

        <Matrix M11=”1″ M12=”2″ M21=”.5″ M22=”.3″ OffsetX=”.3″ OffsetY=”2″ />

    MatrixTransform.Matrix>

MatrixTransform>

lub szybciej:

<Button Content=”OK” Width=”80″ Height=”80″ RenderTransform=”1,2,.5,.3,.3,2″>

Łączenie transformacji

LayoutTransform oraz RenderTransform są typu ContentControl i jako swoje dziecko pozwalają ustawić tylko jedną transformację. Jeśli chcemy połączyć ich kilka to musimy skorzystać z elementu TransformGroup. Będziemy mogli wtedy użyć większej ich ilości. Przykład:

<Button.RenderTransform>

    <TransformGroup>

        <ScaleTransform ScaleX=”.5″ ScaleY=”.5″ />

        <RotateTransform Angle=”45″ CenterX=”.5″ CenterY=”.5″/>

        <TranslateTransform X=”45″ Y=”45″ />

    TransformGroup>

Button.RenderTransform>

Uwaga dla osób, które pierwszy raz z tym się stykają. Złączenie np. obrotu i przesunięcia to nie to samo co złączenie przesunięcia i obrotu. Kolejność ma znaczenie.

Do zapamiętania

Wszelkie te operacje, choć tak to wygląda nie zmieniają rozmiarów kontrolki odczytanych za pomocą Height, Width, ActualWidth, ActualHeight. Mimo np. przeskalowania przycisku 20×20 dwa razy, wartości, które odczytamy będą nadal wskazywały na rozmiar 20×20.

Na dziś tyle. Następnym razem już w końcu omówienie paneli.