Freigeben über


Zeichnen von Formen

Erfahren Sie, wie Sie Formen zeichnen, z. B. Ellipsen, Rechtecke, Polygone und Pfade. Die Path-Klasse ist die Möglichkeit, eine ziemlich komplexe vektorbasierte Zeichnungssprache in einer XAML-Benutzeroberfläche zu visualisieren; Sie können z. B. Bézierkurven zeichnen.

Zwei Klassensätze definieren einen Bereich des Raums in der XAML-Benutzeroberfläche: Shape-Klassen und Geometrieklassen . Der Hauptunterschied zwischen diesen Klassen besteht darin, dass einem Shape ein Pinsel zugeordnet ist und auf dem Bildschirm gerendert werden kann, und eine Geometrie definiert einfach einen Bereich des Raums und wird nur gerendert, wenn sie Informationen zu einer anderen UI-Eigenschaft beiträgt. Sie können sich ein Shape als UIElement vorstellen, dessen Begrenzung durch eine Geometrie definiert ist. In diesem Thema werden hauptsächlich die Shape-Klassen behandelt.

Die Shape-Klassen sind Line, Ellipse, Rectangle, Polygon, Polyline und Path. Der Pfad ist interessant, da er eine beliebige Geometrie definieren kann und die Geometry-Klasse hier beteiligt ist, da dies eine Möglichkeit ist, die Teile eines Pfads zu definieren.

Füllung und Strich für Formen

Damit ein Shape auf der App-Leinwand gerendert wird, müssen Sie es mit einem Brush verbinden. Legen Sie die Fill-Eigenschaft der Form auf den gewünschten Brush fest. Weitere Informationen zu Pinsel finden Sie unter Verwenden von Pinsel.

Eine Form kann auch einen Strich aufweisen, bei dem es sich um eine Linie handelt, die um den Rand der Form gezeichnet wird. Ein Strich erfordert auch einen Pinsel , der seine Darstellung definiert und einen Wert ungleich Null für StrokeThickness aufweisen sollte. StrokeThickness ist eine Eigenschaft, die die Dicke der Linie um den Rand der Form definiert. Wenn Sie keinen Pinselwert für "Stroke" angeben oder " StrokeThickness " auf 0 festlegen, wird der Rahmen um die Form nicht gezeichnet.

Ellipse

Eine Ellipse ist eine Form mit einem gekrümmten Umkreis. Um eine einfache Ellipse zu erstellen, geben Sie eine Breite, Höhe und einen Pinsel für die Füllung an.

Im nächsten Beispiel wird eine Ellipse mit einer Breite von 200 und einer Höhe von 200 erstellt und ein SteelBlue farbiges SolidColorBrush-Element als Füllung verwendet.

<Ellipse Fill="SteelBlue" Height="200" Width="200" />
var ellipse1 = new Ellipse();
ellipse1.Fill = new SolidColorBrush(Colors.SteelBlue);
ellipse1.Width = 200;
ellipse1.Height = 200;

// When you create a XAML element in code, you have to add
// it to the XAML visual tree. This example assumes you have
// a panel named 'layoutRoot' in your XAML file, like this:
// <Grid x:Name="layoutRoot>
layoutRoot.Children.Add(ellipse1);

Hier sehen Sie die gerenderte Ellipse.

Eine gerenderte Ellipse.

In diesem Fall ist die Ellipse das, was die meisten Personen als Kreis betrachten würden, aber so deklarieren Sie eine Kreisform in XAML: Verwenden Sie eine Ellipse mit gleicher Breite und Höhe.

Wenn eine Ellipse in einem UI-Layout positioniert ist, wird davon ausgegangen, dass ihre Größe mit einem Rechteck mit dieser Breite und Höhe identisch ist; der Bereich außerhalb des Perimeters hat kein Rendering, ist aber weiterhin Teil seiner Layoutplatzgröße.

Ein Satz von 6 Ellipse-Elementen ist Teil der Steuerelementvorlage für das ProgressRing-Steuerelement , und 2 konzentrische Ellipse-Elemente sind Teil eines RadioButton.

Rechteck

Ein Rechteck ist eine vierseitige Form, deren gegenüberliegende Seiten gleich sind. Um ein einfaches Rechteck zu erstellen, geben Sie eine Breite, eine Höhe und eine Füllung an.

Sie können die Ecken eines Rechtecks runden. Um abgerundete Ecken zu erstellen, geben Sie einen Wert für die Eigenschaften RadiusX und RadiusY an. Diese Eigenschaften geben die X-Achse und die Y-Achse einer Ellipse an, die die Kurve der Ecken definiert. Der maximal zulässige Wert von RadiusX ist die Breite dividiert durch zwei und der maximal zulässige Wert von RadiusY ist die Höhe dividiert durch zwei.

Im nächsten Beispiel wird ein Rechteck mit einer Breite von 200 und einer Höhe von 100 erstellt. Es verwendet einen Blue-Wert von SolidColorBrush für seine Füllung und einen Schwarzen Wert von SolidColorBrush für seinen Stroke. Wir legen die StrokeThickness auf 3 fest. Wir legen die RadiusX-Eigenschaft auf 50 und die RadiusY-Eigenschaft auf 10 fest, wodurch das Rechteck abgerundet wird.

<Rectangle Fill="Blue"
           Width="200"
           Height="100"
           Stroke="Black"
           StrokeThickness="3"
           RadiusX="50"
           RadiusY="10" />
var rectangle1 = new Rectangle();
rectangle1.Fill = new SolidColorBrush(Colors.Blue);
rectangle1.Width = 200;
rectangle1.Height = 100;
rectangle1.Stroke = new SolidColorBrush(Colors.Black);
rectangle1.StrokeThickness = 3;
rectangle1.RadiusX = 50;
rectangle1.RadiusY = 10;

// When you create a XAML element in code, you have to add
// it to the XAML visual tree. This example assumes you have
// a panel named 'layoutRoot' in your XAML file, like this:
// <Grid x:Name="layoutRoot>
layoutRoot.Children.Add(rectangle1);

Hier sehen Sie das gerenderte Rechteck.

Ein gerendertes Rechteck.

Es gibt einige Szenarien für UI-Definitionen, in denen anstelle eines Rechtecks ein Rahmen besser geeignet ist. Wenn Sie beabsichtigen, eine Rechteckform um andere Inhalte herum zu erstellen, empfiehlt es sich möglicherweise, Rahmen zu verwenden, da sie untergeordnete Inhalte enthalten kann und diese Inhalte automatisch vergrößert, anstatt die festen Abmessungen für Höhe und Breite wie "Rectangle " zu verwenden. Ein Rahmen hat auch die Möglichkeit, abgerundete Ecken zu haben, wenn Sie die CornerRadius-Eigenschaft festlegen.

Andererseits ist ein Rechteck wahrscheinlich eine bessere Wahl für die Steuerelementkomposition. Ein Rechteck wird in vielen Steuerelementvorlagen angezeigt, da es als "FocusVisual"-Teil für fokussierbare Steuerelemente verwendet wird. Wann immer sich das Steuerelement in einem visuellen Fokussierungszustand "Fokussiert" befindet, wird dieses Rechteck sichtbar gemacht, in anderen Zuständen ist es ausgeblendet.

Polygon

Ein Polygon ist eine Form mit einer Grenze, die durch eine beliebige Anzahl von Punkten definiert wird. Die Grenze wird durch Verbinden einer Linie von einem Punkt zum nächsten erstellt, wobei der letzte Punkt mit dem ersten Punkt verbunden ist. Die Points -Eigenschaft definiert die Sammlung von Punkten, die die Grenze bilden. In XAML definieren Sie die Punkte mit einer durch Trennzeichen getrennten Liste. In CodeBehind verwenden Sie eine PointCollection , um die Punkte zu definieren, und Sie fügen jeden einzelnen Punkt als Punktwert zur Auflistung hinzu.

Sie müssen die Punkte nicht explizit deklarieren, sodass der Startpunkt und der Endpunkt beide als derselbe Punktwert angegeben werden. Die Renderinglogik für ein Polygon geht davon aus, dass Sie ein geschlossenes Shape definieren und den Endpunkt implizit mit dem Startpunkt verbinden.

Im nächsten Beispiel wird ein Polygon mit vier Punkten erstellt, die auf (10,200), (60,140), (130,140) und (180,200) gesetzt sind. Es verwendet einen LightBlue-Wert von SolidColorBrush für seine Füllung und hat keinen Wert für Stroke , sodass er keine Umrandung aufweist.

<Polygon Fill="LightBlue"
         Points="10,200,60,140,130,140,180,200" />
var polygon1 = new Polygon();
polygon1.Fill = new SolidColorBrush(Colors.LightBlue);

var points = new PointCollection();
points.Add(new Windows.Foundation.Point(10, 200));
points.Add(new Windows.Foundation.Point(60, 140));
points.Add(new Windows.Foundation.Point(130, 140));
points.Add(new Windows.Foundation.Point(180, 200));
polygon1.Points = points;

// When you create a XAML element in code, you have to add
// it to the XAML visual tree. This example assumes you have
// a panel named 'layoutRoot' in your XAML file, like this:
// <Grid x:Name="layoutRoot>
layoutRoot.Children.Add(polygon1);

Hier sehen Sie das gerenderte Polygon.

Ein gerendertes Polygon.

Tipp

Ein Punktwert wird häufig als Typ in XAML für andere Szenarien als das Deklarieren der Scheitelpunkte von Shapes verwendet. Beispielsweise ist ein Punkt Teil der Ereignisdaten für Touchereignisse, sodass Sie genau wissen können, wo in einem Koordinatenbereich die Touchaktion aufgetreten ist. Weitere Informationen zu Point und deren Verwendung in XAML oder Code finden Sie im API-Referenzthema zu Point.

Zeilen

Eine Linie ist einfach eine Linie, die zwischen zwei Punkten im Koordinatenbereich gezeichnet wird. Eine Linie ignoriert alle für Fill bereitgestellten Werte, da sie keinen Innenbereich aufweist. Stellen Sie für eine Linie sicher, dass Sie Werte für die Eigenschaften Stroke und StrokeThickness angeben, da andernfalls die Linie nicht gerendert wird.

Sie verwenden keine Punktwerte , um ein Linien-Shape anzugeben. Stattdessen verwenden Sie diskrete Double-Werte für X1, Y1, X2 und Y2. Dies ermöglicht minimales Markup für horizontale oder vertikale Linien. Definiert beispielsweise <Line Stroke="Red" X2="400"/> eine horizontale Linie, die 400 Pixel lang ist. Die anderen X,Y-Eigenschaften sind standardmäßig 0, sodass dieser XAML-Code in Bezug auf Punkte eine Linie von (0,0) zu (400,0) zeichnen würde. Sie können dann eine TranslateTransform verwenden, um die gesamte Zeile zu verschieben, wenn sie an einem anderen Punkt als (0,0) beginnen soll.

<Line Stroke="Red" X2="400"/>
var line1 = new Line();
line1.Stroke = new SolidColorBrush(Colors.Red);
line1.X2 = 400;

// When you create a XAML element in code, you have to add
// it to the XAML visual tree. This example assumes you have
// a panel named 'layoutRoot' in your XAML file, like this:
// <Grid x:Name="layoutRoot>
layoutRoot.Children.Add(line1);

Polylinie

Eine Polylinie ähnelt einem Polygon , in dem die Grenze der Form durch eine Reihe von Punkten definiert wird, mit der Ausnahme, dass der letzte Punkt in einer Polylinie nicht mit dem ersten Punkt verbunden ist.

Hinweis

Sie könnten explizit einen identischen Anfangs- und Endpunkt in den Punkten haben, die für die Polylinie festgelegt sind, aber in diesem Fall könnten Sie wahrscheinlich stattdessen ein Polygon verwendet haben.

Wenn Sie eine Füllung einer Polylinie angeben, zeichnet die Füllung den Innenbereich der Form, auch wenn sich der Startpunkt und der Endpunkt der für die Polylinie festgelegten Punkte nicht schneiden. Wenn Sie keine Füllung angeben, ähnelt die Polylinie dem, was gerendert würde, wenn Sie mehrere einzelne Linienelemente angegeben hätten, in denen die Anfangs- und Endpunkte aufeinander folgender Linien überschneiden.

Wie bei einem Polygon definiert die Points-Eigenschaft die Sammlung von Punkten, die die Grenze bilden. In XAML definieren Sie die Punkte mit einer durch Trennzeichen getrennten Liste. Im CodeBehind verwenden Sie eine PointCollection , um die Punkte zu definieren und jeden einzelnen Punkt als Punktstruktur zur Auflistung hinzuzufügen.

In diesem Beispiel wird eine Polylinie mit vier Punkten erstellt, die auf (10,200), (60,140), (130,140) und (180,200) gesetzt sind. Ein Strich ist definiert, aber keine Füllung.

<Polyline Stroke="Black"
          StrokeThickness="4"
          Points="10,200,60,140,130,140,180,200" />
var polyline1 = new Polyline();
polyline1.Stroke = new SolidColorBrush(Colors.Black);
polyline1.StrokeThickness = 4;

var points = new PointCollection();
points.Add(new Windows.Foundation.Point(10, 200));
points.Add(new Windows.Foundation.Point(60, 140));
points.Add(new Windows.Foundation.Point(130, 140));
points.Add(new Windows.Foundation.Point(180, 200));
polyline1.Points = points;

// When you create a XAML element in code, you have to add
// it to the XAML visual tree. This example assumes you have
// a panel named 'layoutRoot' in your XAML file, like this:
// <Grid x:Name="layoutRoot>
layoutRoot.Children.Add(polyline1);

Dies ist die gerenderte Polylinie. Beachten Sie, dass die ersten und letzten Punkte nicht durch die Strichgliederung verbunden sind, da sie sich in einem Polygon befinden.

Eine gerenderte Polylinie.

Pfad

Ein Pfad ist die vielseitigste Form , da Sie es verwenden können, um eine beliebige Geometrie zu definieren. Aber mit dieser Vielseitigkeit kommt komplexität. Sehen wir uns nun an, wie Sie einen einfachen Pfad in XAML erstellen.

Sie definieren die Geometrie eines Pfads mit der Data-Eigenschaft . Es gibt zwei Techniken zum Festlegen von Daten:

  • Sie können einen Zeichenfolgenwert für Daten in XAML festlegen. In dieser Form nutzt der Path.Data-Wert ein Serialisierungsformat für Grafiken. Sie bearbeiten diesen Wert in der Regel nicht in Zeichenfolgenform, nachdem er zuerst eingerichtet wurde. Stattdessen verwenden Sie Entwurfstools, mit denen Sie in einer Entwurfs- oder Zeichnungsmetapher auf einer Oberfläche arbeiten können. Anschließend speichern oder exportieren Sie die Ausgabe. Dadurch erhalten Sie eine XAML-Datei oder ein XAML-Zeichenfolgenfragment mit Path.Data-Informationen .
  • Sie können die Data-Eigenschaft auf ein einzelnes Geometry-Objekt festlegen. Dies kann im Code oder in XAML erfolgen. Diese einzelne Geometrie ist in der Regel eine GeometryGroup, die als Container fungiert, der mehrere Geometriedefinitionen zu einem einzelnen Objekt für die Zwecke des Objektmodells zusammengesetzt kann. Der häufigste Grund hierfür ist, dass Sie eine oder mehrere der Kurven und komplexen Formen verwenden möchten, die als Segmentwerte für eine PathFigure definiert werden können, z. B. BezierSegment.

Dieses Beispiel zeigt einen Pfad, der möglicherweise durch die Verwendung von Blend für Visual Studio entstanden ist, um nur einige Vektorformen zu erstellen und das Ergebnis dann als XAML zu speichern. Der Gesamtpfad besteht aus einem Bézierkurvensegment und einem Liniensegment. Das Beispiel dient hauptsächlich dazu, Ihnen einige Beispiele dafür zu geben, welche Elemente im Path.Data-Serialisierungsformat vorhanden sind und was die Zahlen darstellen.

Diese Daten beginnen mit dem Bewegungsbefehl, der durch "M" angegeben ist, wodurch ein absoluter Startpunkt für den Pfad festgelegt wird.

Das erste Segment ist eine kubische Bézierkurve, die bei (100,200) beginnt und bei (400,175) endet und mit den beiden Kontrollpunkten (100,25) und (400,350) gezeichnet wird. Dieses Segment wird durch den Befehl "C" in der Daten-Attributzeichenfolge angegeben.

Das zweite Segment beginnt mit einem absoluten horizontalen Linienbefehl "H", der eine Linie angibt, die vom vorherigen Unterpfadendpunkt (400,175) zu einem neuen Endpunkt (280,175)gezeichnet wird. Da es sich um einen Befehl für eine horizontale Linie handelt, ist der angegebene Wert eine X-Koordinate.

<Path Stroke="DarkGoldenRod" 
      StrokeThickness="3"
      Data="M 100,200 C 100,25 400,350 400,175 H 280" />

Hier sehen Sie den gerenderten Pfad.

Screenshot eines einfachen gerenderten Pfads.

Das nächste Beispiel zeigt eine Verwendung der anderen behandelten Technik: eine GeometryGroup mit einer PathGeometry. In diesem Beispiel werden einige der beitragenden Geometrietypen ausgeführt, die als Teil einer PathGeometry-Methode verwendet werden können: PathFigure und die verschiedenen Elemente, die ein Segment in PathFigure.Segments sein können.

<Path Stroke="Black" StrokeThickness="1" Fill="#CCCCFF">
    <Path.Data>
        <GeometryGroup>
            <RectangleGeometry Rect="50,5 100,10" />
            <RectangleGeometry Rect="5,5 95,180" />
            <EllipseGeometry Center="100, 100" RadiusX="20" RadiusY="30"/>
            <RectangleGeometry Rect="50,175 100,10" />
            <PathGeometry>
                <PathGeometry.Figures>
                    <PathFigureCollection>
                        <PathFigure IsClosed="true" StartPoint="50,50">
                            <PathFigure.Segments>
                                <PathSegmentCollection>
                                    <BezierSegment Point1="75,300" Point2="125,100" Point3="150,50"/>
                                    <BezierSegment Point1="125,300" Point2="75,100"  Point3="50,50"/>
                                </PathSegmentCollection>
                            </PathFigure.Segments>
                        </PathFigure>
                    </PathFigureCollection>
                </PathGeometry.Figures>
            </PathGeometry>
        </GeometryGroup>
    </Path.Data>
</Path>
var path1 = new Microsoft.UI.Xaml.Shapes.Path();
path1.Fill = new SolidColorBrush(Windows.UI.Color.FromArgb(255, 204, 204, 255));
path1.Stroke = new SolidColorBrush(Colors.Black);
path1.StrokeThickness = 1;

var geometryGroup1 = new GeometryGroup();
var rectangleGeometry1 = new RectangleGeometry();
rectangleGeometry1.Rect = new Rect(50, 5, 100, 10);
var rectangleGeometry2 = new RectangleGeometry();
rectangleGeometry2.Rect = new Rect(5, 5, 95, 180);
geometryGroup1.Children.Add(rectangleGeometry1);
geometryGroup1.Children.Add(rectangleGeometry2);

var ellipseGeometry1 = new EllipseGeometry();
ellipseGeometry1.Center = new Point(100, 100);
ellipseGeometry1.RadiusX = 20;
ellipseGeometry1.RadiusY = 30;
geometryGroup1.Children.Add(ellipseGeometry1);

var pathGeometry1 = new PathGeometry();
var pathFigureCollection1 = new PathFigureCollection();
var pathFigure1 = new PathFigure();
pathFigure1.IsClosed = true;
pathFigure1.StartPoint = new Windows.Foundation.Point(50, 50);
pathFigureCollection1.Add(pathFigure1);
pathGeometry1.Figures = pathFigureCollection1;

var pathSegmentCollection1 = new PathSegmentCollection();
var pathSegment1 = new BezierSegment();
pathSegment1.Point1 = new Point(75, 300);
pathSegment1.Point2 = new Point(125, 100);
pathSegment1.Point3 = new Point(150, 50);
pathSegmentCollection1.Add(pathSegment1);

var pathSegment2 = new BezierSegment();
pathSegment2.Point1 = new Point(125, 300);
pathSegment2.Point2 = new Point(75, 100);
pathSegment2.Point3 = new Point(50, 50);
pathSegmentCollection1.Add(pathSegment2);
pathFigure1.Segments = pathSegmentCollection1;

geometryGroup1.Children.Add(pathGeometry1);
path1.Data = geometryGroup1;

// When you create a XAML element in code, you have to add
// it to the XAML visual tree. This example assumes you have
// a panel named 'layoutRoot' in your XAML file, like this:
// <Grid x:Name="layoutRoot">
layoutRoot.Children.Add(path1);

Hier sehen Sie den gerenderten Pfad.

Screenshot eines komplexen gerenderten Pfads.

Die Verwendung von PathGeometry kann besser lesbar sein als das Auffüllen einer Path.Data-Zeichenfolge . Auf der anderen Seite verwendet Path.Data eine Syntax, die mit SVG-Bildpfaddefinitionen (Scalable Vector Graphics) kompatibel ist, sodass es nützlich sein kann, Grafiken von SVG zu portieren oder als Ausgabe von einem Tool wie Blend.

UWP und WinUI 2

Von Bedeutung

Die Informationen und Beispiele in diesem Artikel sind für Apps optimiert, die das Windows App SDK und WinUI 3 verwenden, gelten jedoch allgemein für UWP-Apps, die WinUI 2 verwenden. In der UWP-API-Referenz finden Sie plattformspezifische Informationen und Beispiele.

Dieser Abschnitt enthält Informationen, die Sie zum Verwenden des Steuerelements in einer UWP- oder WinUI 2-App benötigen.

APIs für diese Shapes sind im Windows.UI.Xaml.Shapes-Namespace vorhanden.