What is a ContentPresenter?
In WPF there is an element called ContentPresenter, that is often used inside control templates, as well as inside the root application markup. The concept of ContentPresenter is quite simple – it is a placeholder for any XAML content and it can be used to insert content at runtime.
What I personally find it useful for is dynamic user interface, where there is no need to define a static UI structure at design time, but at runtime there should be some components that are either defined in the application XAML or in an external resource.
A content presenter is used via the ContentPresenter element: <ContentPresenter></ContentPresenter>. The content inside this element can be partially (or completely, although its value is lost in this case) defined inside the <ContentPresenter.Content></ContentPresenter.Content> element.
If you consider using the ContentPresenter element by defining the content from scratch, there is no need to include the Content element in the base XAML – it cannot be empty and running it so will cause an exception to be thrown. Once the content is set at runtime, the proper tag will be added automatically.
Let’s take a look at an example. Here is the base XAML for a window:
Title="MainWindow" Height="380" Width="568" Loaded="Window_Loaded">
I am also setting a name for my ContentPresenter, so that I can access it from the code-behind. I did not define any default content, but if I would want to, I would use the following XAML structure:
Here is some sample XAML content to test the basic capabilities:
The namespace is required here. Although you can use namespace-less elements when explicitly defining the content directly in the application, a namespace indicator is required when the content is dynamically placed.
To load the content above, in the code behind I can use this sample code:
StringReader reader = new StringReader(File.ReadAllText("D:\\Temporary\\button.txt"));
XmlReader xmlReader = XmlReader.Create(reader);
MyContent.Content = (Button)XamlReader.Load(xmlReader);
In this specific example, I am loading the content shown above from a text file. I am then reading it as XML (since XAML is based on XML and the formatting is preserved). The XAML data is then assigned to the Content property for the specified ContentPlaceholder.
I am parsing it via the XamlReader, that will read the elements and assign them properly. Notice the fact that I am explicitly converting the XAML content to a Button. I need to do this so that the content is correctly rendered. Otherwise, an exception will be thrown.
You might be wondering – well, with the same success you could be using a stackpanel or a grid. But this is not always the case. When control templates are built, there is a well-defined element hierarchy and sometimes using a defined container is not a choice. A content presenter can be a holder for any controls and can be bound to the content from various elements via TemplateBinding, if used in a template.