## 22.2 Path-Elemente In den vorhergehenden Abschnitten haben wir uns einige von Shape abgeleitete Klassen angesehen. Eine Klasse haben wir noch nicht betrachtet: Path. Von allen Shapes ist Path sicherlich das mächtigste und vielseitigste mit den meisten Möglichkeiten, denn mit Path lassen sich auch komplexeste Figuren darstellen. Ein Path beschreibt eine geometrische Figur natürlich ebenfalls mit Linien, Kreisen, usw. Sollten Sie jetzt aber der Meinung sein, hier die bereits behandelten Elemente wie Line der Ellipse verwenden zu können, liegen Sie falsch. Stattdessen verwendet Path andere Elemente, die von der Klasse Geometry abgeleitet sind und in ihrem Bezeichner das Suffix Geometry haben. Dazu gehören LineGeometry, EllipseGeometry und RectangleGeometry. Ein wesentliches Unterscheidungsmerkmal zwischen Line und LineGeometry ist beispielsweise, dass LineGeometry nicht auf Ereignisse reagiert – ganz im Gegensatz zu Line. Das gilt auch für die anderen Geometry-Objekte. Ein anderes Merkmal ist, dass sich Geometry-Elemente nicht selbst zeichnen können – sie sind beispielsweise auf Path angewiesen. Die Eigenschaften Fill oder Stroke werden Sie daher vergeblich in Geometry-Elementen suchen. Die geometrische Figur, die durch Path beschrieben wird, gibt man der Path-Eigenschaft Data an, die Geometry-Elemente akzeptiert. Dabei kann es sich im einfachsten Fall um genau ein Element handeln, aber auch um mehrere. Genug der Worte, sehen wir uns nun die Festlegung einer Ellipse mit Path an:
    <Path Stroke="Black">
      <Path.Data>
        <EllipseGeometry Center="100,100" RadiusX="100" RadiusY="60" />
      </Path.Data>
    </Path>
Es fällt vermutlich sofort auf, dass die Größe der Ellipse nun nicht mehr durch Height und Width bestimmt wird, sondern mit der Eigenschaft Center. Die Größe der Ellipse wird durch RadiusX und RadiusY festgelegt. RadiusX beschreibt dabei den Radius in X-Richtung, RadiusY den Radius in Y-Richtung. Ein ähnlicher Unterschied findet sich auch zwischen den Klassen Rectangle und RectangleGeometry. Hier wird die Eigenschaft Rect dazu benutzt, die relative Position und die Abmessungen festzulegen.
    <Path Stroke="Black">
      <Path.Data>
        <RectangleGeometry Rect="40,10,100,150" RadiusX="20" RadiusY="50" />
      </Path.Data>
    </Path>
Die beiden ersten Zahlen geben die Position des Bezugspunktes an (das ist die linke obere Ecke), die beiden letzten die Breite und Höhe. Mit RadiusX und RadiusY können Sie die Ecken sogar mit den angegebenen Radien runden. ### 22.2.1 GeometryGroup So wie in den beiden Listings zuvor gezeigt, können Sie nur eine geometrische Figur ausgeben. Natürlich ließen sich mehrere Path-Elemente angeben, um zumindest optisch eine komplexe Figur zu erstellen. Aber es gibt auch einen anderen Weg, bei dem Hilfsklassen zum Einsatz kommen. Unter Zuhilfenahme von Hilfsklassen lassen sich mehrere geometrische Figuren zu einer Gesamtfigur zusammenfassen Zu diesen Hilfsklassen gehört GeometryGroup, die im folgenden Listing ein EllipseGeometry- und ein RectangleGeometry-Element kombiniert. Die Ausgabe sehen Sie in Abbildung 22.4.
    <Path Fill="Blue">
      <Path.Data>
        <GeometryGroup FillRule="Nonzero">
          <EllipseGeometry Center="200,185" RadiusX="30" RadiusY="20" />
          <RectangleGeometry Rect="110,110,100,150" RadiusX="20" RadiusY="50" />
        </GeometryGroup>
      </Path.Data>
    </Path>
Mit Fill wird die Füllfarbe Blau festgelegt, die für den gesamten umschlossenen Bereich der Figur steht. In die Data-Eigenschaft ist das GeometryGroup-Element eingebettet, das seinerseits die Geometry-Elemente des Rechtecks und der Ellipse enthält. Hier klicken, um das Bild zu vergrößern Abbildung 22.4 Die durch »GeometryGroup« beschriebene geometrische Figur Beachten Sie hierbei auch die Eigenschaft FillRule, mit der beschrieben wird, wie die sich überschneidenden Bereiche der Objekte kombiniert werden. FillRule kann durch EvenOdd und Nonzero beschrieben werden. In Abbildung 22.5 ist die Einstellung EvenOdd. Hier klicken, um das Bild zu vergrößern Abbildung 22.5 Auswirkung der Einstellung »EvenOdd« der Eigenschaft »FillRule« ### 22.2.2 CombinedGeometry Mit GeometryGroup lassen sich beliebig viele Geometry-Elemente kombinieren, mit CombinedGeometry nur zwei. CombinedGeometry weist mit GeometryCombineMode eine besondere Eigenschaft auf, mit der die Kombination der beiden Elemente beschrieben wird. Die Eigenschaft ist vom Typ der Enumeration GeometryCombineMode, die die Werte Exclude, Intersect, Union und Xor enthält. Die Auswirkungen sehen Sie in Abbildung 22.6. Hier klicken, um das Bild zu vergrößern Abbildung 22.6 Auswirkungen der Eigenschaft »GeometryCombineMode« Abbildung 22.6 liegt der folgende XAML-Code zugrunde:
    <Canvas>
      <Path Fill="Blue">
        <Path.Data>
          <CombinedGeometry GeometryCombineMode="Xor">
            <CombinedGeometry.Geometry1>
              <EllipseGeometry Center="100,100" RadiusX="50" RadiusY="50" />
            </CombinedGeometry.Geometry1>
            <CombinedGeometry.Geometry2>
              <EllipseGeometry Center="150,100" RadiusX="50" RadiusY="50" />
            </CombinedGeometry.Geometry2>
          </CombinedGeometry>
        </Path.Data>
      </Path>
    </Canvas>
Die beiden Geometry-Objekte müssen mit den beiden Eigenschaften Geometry1 und Geometry2 zugeordnet werden. Anders als bei einer GeometryGroup wird aus der durch die blaue Farbe gekennzeichnete Fläche eine neue geometrische Figur geschaffen. ### 22.2.3 PathGeometry GeometryGroup und CombinedGeometry sind in ihren Möglichkeiten noch beschränkt. Zur Darstellung auch komplexester geometrischer Figuren ist das Element PathGeometry bestens geeignet. Die resultierende Gesamtfigur wird dabei in mehrere einzelne Figuren zerlegt, deren Linien schrittweise zusammengefügt werden. Diese Vorgehensweise erfordert viel Detailarbeit, woraus am Ende auch ein unter Umständen sehr komplexer XAML-Code resultiert. Das folgende Codebeispiel demonstriert den Einsatz des PathGeometry-Elements. Die Ausgabe ist kaum der Rede wert, es handelt sich um ein einfaches Quadrat.
    <Canvas>
      <Path Stroke="#FF000000">
        <Path.Data>
          <PathGeometry>
            <PathGeometry.Figures>
              <PathFigure StartPoint="0,0" IsClosed="True">
                <LineSegment Point="100,0" />
                <LineSegment Point="100,100" />
                <LineSegment Point="0,100" />
              </PathFigure>
            </PathGeometry.Figures>
          </PathGeometry>
        </Path.Data>
      </Path>
    </Canvas>
Innerhalb des PathGeometry-Elements ist in der Eigenschaft Figures ein PathFigure-Element eingebettet. In diesem Beispiel handelt es sich nur um ein PathFigure-Element, es können aber x-beliebig viele sein. In PathFigure sind die grafischen Elemente eingebettet. An der namentlichen Kennzeichnung können Sie bereits erkennen, dass es sich um eine ganz besondere Gruppe von Elementen handelt. Tatsächlich müssen sie von PathSegment abgeleitet sein. PathSegment zeichnet sich nur durch zwei Eigenschaften aus: Mit IsStroked kann festgelegt werden, ob ein Element gezeichnet werden soll, und mit IsSmoothJoin legen Sie fest, ob die Verbindung zum Vorgängerelement abgerundet werden soll oder nicht.