Search code examples
c#wpfdrawingcontextdrawingvisual

How to programatically resize a DrawingVisual?


So, I'm new to WPF Drawing. For performance reasons, I've had to switch from regular controls like ContentControl and UserControl to more light-weight elements like DrawingVisual. I am working on a diagramming app which would probably have a max of 1000 elements on the canvas that can be dragged, resized and such. Firstly, is it better to use DrawingVisual instead of Shape? Secondly, my main question here. I am adding DrawingVisual elements to the Canvas as such:

public class SVisualContainer : UIElement
{
    // Create a collection of child visual objects.
    private VisualCollection _children;

    public SVisualContainer()
    {
        _children = new VisualCollection(this);
        _children.Add(CreateDrawingVisualRectangle());
    }

    // 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, null, rect);

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

        return drawingVisual;
    }

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

And within the canvas:

public void AddStateVisual()
{
    var sVisual = new SVisualContainer();
    Children.Add(sVisual);
    Canvas.SetLeft(sVisual, 10);
    Canvas.SetTop(sVisual, 10);
}

How can I increase the size of the Rectangle dynamically through code? I have tried setting the Height and Width of the Rectangle which did not work, played around with the ScaleTransform but that is probably not what I want. Would I need to redraw the Rectangle? Thanks!


Solution

  • I ended up using DrawingVisual within UIElement as shown in the question, and continuously redrawing the DrawingVisual upon resize. The UIElement.RenderSize property, UIElement.MeasureCore method and UIElement.InvalidateMeasure method are central to this. This works quite well and the performance is acceptable.