Quando dobbiamo realizzare forme complesse, non possiamo più utilizzare direttamente le classi per disegnare primitive grafiche come Line
piuttosto che Ellipse
, ma dobbiamo utilizzare un altro l'elemento, che eredita sempre da Shape, ma ben più potente e versatile degli altri, l'oggetto Path.
Path espone un'unica proprietà: Data
, di tipo Geometry
, è utilizzata per definire la struttura della forma da rappresentare, sia tramite l'utilizzo del relativo modello ad oggetti, sia tramite uno specifico mini-linguaggio.
Il tipo Geometry
è astratto quindi esistono una serie di classi che ereditano da esso e che specificano la forma che sarà rappresentata. La maggior parte degli oggetti Geometry
permettono di creare le forme e linee viste nelle lezioni precedenti, per esempio possiamo creare una linea ed un ellisse tramite Path e gli elementi LineGeometry
ed EllipseGeometry
.
<Path Stroke="Green" StrokeThickness="10"> <Path.Data> <LineGeometry StartPoint="20,20" EndPoint="100,20" /> </Path.Data> </Path> <Path Margin="10" Fill="Blue" Stroke="Black"> <Path.Data> <EllipseGeometry RadiusX="50" RadiusY="25" Center="50,25" /> </Path.Data> </Path>
Fino ora niente di nuovo, però possiamo già notare un piccolo particolare, Geometry
definisce le proprietà della forma che sarà rappresentata mentre Path
espone solo le proprietà legate al disegno della figura. Grazie a questa separazione delle responsabilità ed agli elementi GeometryGroup e PathGeometry possiamo creare figure molto complesse. GeometryGroup
permette di raggruppare più elementi Geometry
in uno.
<Path Fill="Purple" Stroke="Black" Margin="10" StrokeThickness="10"> <Path.Data> <GeometryGroup> <RectangleGeometry Rect="0,0 100,100" /> <EllipseGeometry Center="50,50" RadiusX="35" RadiusY="25" /> </GeometryGroup> </Path.Data> </Path> <Path Fill="Purple" Stroke="Black" Margin="10" StrokeThickness="10"> <Path.Data> <GeometryGroup> <RectangleGeometry Rect="0,0 100,100" /> <EllipseGeometry Center="50,50" RadiusX="35" RadiusY="25" /> </GeometryGroup> </Path.Data> </Path>
Le strategie di riempimento delle forme, definite dalla proprietà FillRule
, sono le solite due, EvenOdd
e NonZero
, di cui abbiamo parlato nelle lezioni precedenti. Nell'ultimo esempio impostando la proprietà FillRule
, esposta dall'oggetto GeometryGroup
, a NonZero
otteniamo il seguente risultato:
Il fatto più interessante di questo esempio è che in questo caso stiamo creando un'unica figura, non una semplice sovrapposizione dei due oggetti Rectangle
e Ellipse
. Abbiamo quindi un unico elemento per l'interfaccia utente, vantaggio che si rivela importante in termini di performance, quando visualizziamo immagini molto complesse, realizzate assemblando e sovrapponendo fra loro molti oggetti Geometry
.