Search code examples
wpfcontentcontrol

WPF - ContentControl Content as DrawingVisual


Can I set the Content property of a ContentControl to a DrawingVisual object? It says in the documentation that the content can be anything but I tried and nothing shows up when I add the control to canvas. Is it possible and if it is can you post the full code that adds a ContentControl, whose content is a DrawingVisual, to a canvas?


Solution

  • Can I set the Content property of a ContentControl to a DrawingVisual object?

    Technically, yes, you can. However, that is probably not what you want. A DrawingVisual added to a ContentControl will simply display the string "System.Windows.Media.DrawingVisual". The following code within a grid will demonstrate this easilly:

    <Button>
        <DrawingVisual/>
    </Button>
    

    To use a DrawingVisual properly, you need to encapsulate it within a FrameworkElement. See the Microsoft Reference.

    Thus, the following code should help do what you want.

    <Window x:Class="TestDump.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:TestDump"
    Title="Window1" Height="300" Width="600" >
    <Grid>
        <Canvas>
            <Button >
                <local:MyVisualHost Width="600" Height="300"/>
            </Button>
        </Canvas>
    </Grid>
    </Window>
    

    And on the C# side:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    namespace TestDump
    {
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }
    }
    
    public class MyVisualHost : FrameworkElement
    {
        private VisualCollection _children;
        public MyVisualHost()
        {
            _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.Blue, (System.Windows.Media.Pen)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];
        }
    
    }
    }