Utilizzo degli oggetti DrawingVisual
In questo argomento vengono forniti cenni preliminari sull'utilizzo di oggetti DrawingVisual al livello visivo di WPF.
Di seguito sono elencate le diverse sezioni di questo argomento.
Oggetto DrawingVisual
Contenitore host di DrawingVisual
Creazione di oggetti DrawingVisual
Creazione di override per i membri FrameworkElement
Supporto per l'hit testing
Argomenti correlati
Oggetto DrawingVisual
DrawingVisual è una classe di disegno semplificata utilizzata per il rendering di forme, immagini o testo. Questa classe è considerata semplice perché non fornisce la gestione del layout o degli eventi, migliorando in tal modo le prestazioni. Per questo motivo, i disegni sono ideali per gli sfondi e per ClipArt.
Contenitore host di DrawingVisual
Per utilizzare oggetti DrawingVisual è necessario creare un contenitore host. L'oggetto contenitore host deve derivare dalla classe FrameworkElement che fornisce il layout e il supporto per la gestione di eventi che mancano alla classe DrawingVisual. Tramite l'oggetto contenitore host non vengono visualizzate proprietà visibili, poiché lo scopo principale di questo oggetto è quello di contenere oggetti figlio. Tuttavia, è necessario impostare la proprietà Visibility del contenitore host su Visible. In caso contrario, nessuno degli elementi figlio sarà visibile.
Quando si crea un oggetto contenitore host per gli oggetti visivi, è necessario archiviare i riferimenti agli oggetti visivi in VisualCollection. Utilizzare il metodo Add per aggiungere un oggetto visivo al contenitore host. Nell'esempio riportato di seguito, viene creato un oggetto contenitore host e tre oggetti visivi vengono aggiunti a VisualCollection.
' Create a host visual derived from the FrameworkElement class.
' This class provides layout, event handling, and container support for
' the child visual objects.
Public Class MyVisualHost
Inherits FrameworkElement
' Create a collection of child visual objects.
Private _children As VisualCollection
Public Sub New()
_children = New VisualCollection(Me)
_children.Add(CreateDrawingVisualRectangle())
_children.Add(CreateDrawingVisualText())
_children.Add(CreateDrawingVisualEllipses())
' Add the event handler for MouseLeftButtonUp.
AddHandler MouseLeftButtonUp, AddressOf MyVisualHost_MouseLeftButtonUp
End Sub
// Create a host visual derived from the FrameworkElement class.
// This class provides layout, event handling, and container support for
// the child visual objects.
public class MyVisualHost : FrameworkElement
{
// Create a collection of child visual objects.
private VisualCollection _children;
public MyVisualHost()
{
_children = new VisualCollection(this);
_children.Add(CreateDrawingVisualRectangle());
_children.Add(CreateDrawingVisualText());
_children.Add(CreateDrawingVisualEllipses());
// Add the event handler for MouseLeftButtonUp.
this.MouseLeftButtonUp += new System.Windows.Input.MouseButtonEventHandler(MyVisualHost_MouseLeftButtonUp);
}
Nota |
---|
Per l'esempio di codice completo dal quale è stato estratto l'esempio di codice precedente, vedere Esempio di hit test mediante DrawingVisual (la pagina potrebbe essere in inglese). |
Creazione di oggetti DrawingVisual
Quando viene creato, un oggetto DrawingVisual non ha contenuto di disegno. È possibile aggiungere contenuto di testo, grafica o immagini recuperando DrawingContext per l'oggetto e disegnandovi. DrawingContext viene restituito chiamando il metodo RenderOpen di un oggetto DrawingVisual.
Per disegnare un rettangolo in DrawingContext utilizzare il metodo DrawRectangledell'oggetto DrawingContext. Sono disponibili metodi simili per disegnare altri tipi di contenuto. Al termine delle operazioni di disegno del contenuto in DrawingContext, chiamare il metodo Close per chiudere DrawingContext e mantenere il contenuto.
Nell'esempio riportato di seguito, viene creato un oggetto DrawingVisual e viene disegnato un rettangolo in DrawingContext.
' Create a DrawingVisual that contains a rectangle.
Private Function CreateDrawingVisualRectangle() As DrawingVisual
Dim drawingVisual As New DrawingVisual()
' Retrieve the DrawingContext in order to create new drawing content.
Dim drawingContext As DrawingContext = drawingVisual.RenderOpen()
' Create a rectangle and draw it in the DrawingContext.
Dim rect As New Rect(New Point(160, 100), New Size(320, 80))
drawingContext.DrawRectangle(Brushes.LightBlue, CType(Nothing, Pen), rect)
' Persist the drawing content.
drawingContext.Close()
Return drawingVisual
End Function
// Create a DrawingVisual that contains a rectangle.
private DrawingVisual CreateDrawingVisualRectangle()
{
DrawingVisual drawingVisual = new DrawingVisual();
// Retrieve the DrawingContext in order to create new drawing content.
DrawingContext drawingContext = drawingVisual.RenderOpen();
// Create a rectangle and draw it in the DrawingContext.
Rect rect = new Rect(new System.Windows.Point(160, 100), new System.Windows.Size(320, 80));
drawingContext.DrawRectangle(System.Windows.Media.Brushes.LightBlue, (System.Windows.Media.Pen)null, rect);
// Persist the drawing content.
drawingContext.Close();
return drawingVisual;
}
Creazione di override per i membri FrameworkElement
L'oggetto contenitore host è responsabile della gestione dell'insieme di oggetti visivi. A tale scopo, è necessario che il contenitore host implementi l'override di membri per la classe FrameworkElement derivata.
Nell'elenco riportato di seguito vengono descritti due membri per i quali è necessario eseguire l'override:
GetVisualChild: restituisce un elemento figlio in corrispondenza dell'indice specificato dall'insieme di elementi figlio.
VisualChildrenCount: ottiene il numero di elementi figlio visivi all'interno di questo elemento.
Nell'esempio riportato di seguito, viene implementato l'override per i due membri FrameworkElement.
' Provide a required override for the VisualChildrenCount property.
Protected Overrides ReadOnly Property VisualChildrenCount() As Integer
Get
Return _children.Count
End Get
End Property
' Provide a required override for the GetVisualChild method.
Protected Overrides Function GetVisualChild(ByVal index As Integer) As Visual
If index < 0 OrElse index >= _children.Count Then
Throw New ArgumentOutOfRangeException()
End If
Return _children(index)
End Function
// Provide a required override for the VisualChildrenCount property.
protected override int VisualChildrenCount
{
get { return _children.Count; }
}
// Provide a required override for the GetVisualChild method.
protected override Visual GetVisualChild(int index)
{
if (index < 0 || index >= _children.Count)
{
throw new ArgumentOutOfRangeException();
}
return _children[index];
}
Supporto per l'hit testing
L'oggetto contenitore host può fornire la gestione degli eventi, anche se non visualizza alcuna proprietà visibile. Si noti tuttavia che la proprietà Visibility del contenitore deve essere impostata su Visible. Consente di creare una routine di gestione degli eventi per il contenitore host in grado di intercettare eventi del mouse, ad esempio il rilascio del pulsante sinistro del mouse. Tramite la routine di gestione degli eventi è quindi possibile implementare l'hit testing richiamando il metodo HitTest. Il parametro HitTestResultCallback del metodo fa riferimento a una procedura definita dall'utente che è possibile utilizzare per determinare l'azione risultante di un hit test.
Nell'esempio riportato di seguito, il supporto per l'hit testing viene implementato per l'oggetto contenitore host e i relativi elementi figlio.
' Capture the mouse event and hit test the coordinate point value against
' the child visual objects.
Private Sub MyVisualHost_MouseLeftButtonUp(ByVal sender As Object, ByVal e As MouseButtonEventArgs)
' Retreive the coordinates of the mouse button event.
Dim pt As Point = e.GetPosition(CType(sender, UIElement))
' Initiate the hit test by setting up a hit test result callback method.
VisualTreeHelper.HitTest(Me, Nothing, New HitTestResultCallback(AddressOf myCallback), New PointHitTestParameters(pt))
End Sub
' If a child visual object is hit, toggle its opacity to visually indicate a hit.
Public Function myCallback(ByVal result As HitTestResult) As HitTestResultBehavior
If result.VisualHit.GetType() Is GetType(DrawingVisual) Then
If (CType(result.VisualHit, DrawingVisual)).Opacity = 1.0 Then
CType(result.VisualHit, DrawingVisual).Opacity = 0.4
Else
CType(result.VisualHit, DrawingVisual).Opacity = 1.0
End If
End If
' Stop the hit test enumeration of objects in the visual tree.
Return HitTestResultBehavior.Stop
End Function
// Capture the mouse event and hit test the coordinate point value against
// the child visual objects.
void MyVisualHost_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
// Retreive the coordinates of the mouse button event.
System.Windows.Point pt = e.GetPosition((UIElement)sender);
// Initiate the hit test by setting up a hit test result callback method.
VisualTreeHelper.HitTest(this, null, new HitTestResultCallback(myCallback), new PointHitTestParameters(pt));
}
// If a child visual object is hit, toggle its opacity to visually indicate a hit.
public HitTestResultBehavior myCallback(HitTestResult result)
{
if (result.VisualHit.GetType() == typeof(DrawingVisual))
{
if (((DrawingVisual)result.VisualHit).Opacity == 1.0)
{
((DrawingVisual)result.VisualHit).Opacity = 0.4;
}
else
{
((DrawingVisual)result.VisualHit).Opacity = 1.0;
}
}
// Stop the hit test enumeration of objects in the visual tree.
return HitTestResultBehavior.Stop;
}