Partager via


Using DrawingVisual Objects

This topic provides an overview of how to use DrawingVisual objects in the WPF visual layer.

This topic contains the following sections.

  • DrawingVisual Object
  • DrawingVisual Host Container
  • Creating DrawingVisual Objects
  • Creating Overrides for FrameworkElement Members
  • Providing Hit Testing Support
  • Related Topics

DrawingVisual Object

The DrawingVisual is a lightweight drawing class that is used to render shapes, images, or text. This class is considered lightweight because it does not provide layout or event handling, which improves its performance. For this reason, drawings are ideal for backgrounds and clip art.

DrawingVisual Host Container

In order to use DrawingVisual objects, you need to create a host container for the objects. The host container object must be derived from the FrameworkElement class, which provides the layout and event handling support that the DrawingVisual class lacks support. The host container object does not display any visible properties, since its main purpose is to contain child objects. However, the Visibility property of the host container must be set to Visible; otherwise, none of its child elements will be visible.

When you create a host container object for visual objects, you need to store the visual object references in a VisualCollection. Use the Add method to add a visual object to the host container. In the following example, a host container object is created, and three visual objects are added to its 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 : 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);
    }
NoteNote:

For the complete code sample from which the preceding code example was extracted, see Using DrawingVisuals Sample.

Creating DrawingVisual Objects

When you create a DrawingVisual object, it has no drawing content. You can add text, graphics, or image content by retrieving the object's DrawingContext and drawing into it. A DrawingContext is returned by calling the RenderOpen method of a DrawingVisual object.

To draw a rectangle into the DrawingContext, use the DrawRectangle method of the DrawingContext object. Similar methods exist for drawing other types of content. When you are finished drawing content into the DrawingContext, call the Close method to close the DrawingContext and persist the content.

In the following example, a DrawingVisual object is created, and a rectangle is drawn into its DrawingContext.

// 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 Point(160, 100), new Size(320, 80));
    drawingContext.DrawRectangle(Brushes.LightBlue, (Pen)null, rect);

    // Persist the drawing content.
    drawingContext.Close();

    return drawingVisual;
}

Creating Overrides for FrameworkElement Members

The host container object is responsible for managing its collection of visual objects. This requires that the host container implement member overrides for the derived FrameworkElement class.

The following list describes the two members you must override:

  • GetVisualChild: Returns a child at the specified index from the collection of child elements.

  • VisualChildrenCount: Gets the number of visual child elements within this element.

In the following example, overrides for the two FrameworkElement members are implemented.

// 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];
}

Providing Hit Testing Support

The host container object can provide event handling even if it does not display any visible properties—however, its Visibility property must be set to Visible. This allows you to create an event handling routine for the host container that can trap mouse events, such as the release of the left mouse button. The event handling routine can then implement hit testing by invoking the HitTest method. The method's HitTestResultCallback parameter refers to a user-defined procedure that you can use to determine the resulting action of a hit test.

In the following example, hit testing support is implemented for the host container object and its children.

// 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.
    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;
}

See Also

Reference

DrawingVisual
HitTest

Concepts

Windows Presentation Foundation Graphics Rendering Overview
Hit Testing in the Visual Layer