While working on a new Xamarin Forms project, I came across the need for a ContentPresenter
ala Microsoft XAML. The basic idea is to use a placeholder for a piece of content (usually a ViewModel) and then supply a DataTemplate
to control how it should be displayed.
A simple example might look like this:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<controls:ContentPresenter Grid.Row="1"
BindingContext="{Binding MyModel, Source={StaticResource Locator}}"
ItemTemplate="{StaticResource MyModelTemplate}"
/>
</Grid>
This goes back to some of the more “classic” MVVM patterns where we want to make our display more componentized.
In Xamarin Forms Today (v1.3.0), if you want to create a custom component, you can derive from ContentView and go to town. Add your widgets either with XAML or in code. Many times though, we don’t really need to create a new class/view directly. A DataTemplate
is sufficient as we can bind to the ViewModel and use Commands to take action. These are the so-called “zero code-behind” views.
In this case, a ContentPresenter is all we need – set the BindingContext
to your ViewModel and create/bind a DataTemplate. New to Forms 1.3, you can now put resources in the Application-level, so you can more easily share those instances.
Here’s the complete code, sans-usings, to implement your own. This can go either in a Shared code or PCL:
public class ContentPresenter : ContentView
{
public static readonly BindableProperty ItemTemplateProperty = BindableProperty.Create("ItemTemplate", typeof(DataTemplate), typeof(ContentPresenter), null, propertyChanged: OnItemTemplateChanged);
private static void OnItemTemplateChanged(BindableObject bindable, object oldvalue, object newvalue)
{
var cp = (ContentPresenter)bindable;
var template = cp.ItemTemplate;
if (template != null)
{
var content = (View)template.CreateContent();
cp.Content = content;
}
else
{
cp.Content = null;
}
}
public DataTemplate ItemTemplate
{
get
{
return (DataTemplate)GetValue(ItemTemplateProperty);
}
set
{
SetValue(ItemTemplateProperty, value);
}
}
}
If you want, you can get fancy with Triggers and change the ItemTemplate
to vary based on whatever conditions you want.
Call It ContentControl. ContentPresenter does something a little differently
https://alexfeinberg.wordpress.com/2014/10/11/wpf-the-real-difference-between-contentcontrol-and-contentpresenter/
Hi Oren,
Thanks for the article! I saw your other article about putting datatemplates in the applications xaml file, which is very useful, is there a way, that you know of, of having a standalone XAML file containing only a datatemplate? Or a trick that would be similar to this?
thanks!
@Alex, I’ve just renamed the control in the XLabs project: https://github.com/XLabs/Xamarin-Forms-Labs/commit/50e40813e27a985583c0464e8d1fd0de0d35fe0b
Do you have any sample coded for this? If so, can you share?
Great idea.
I think it could be simply upgraded to handle a “DataTemplateSelector”.
Nice idea. I think it would be possible to use a DataTemplateSelector with some changes, I’ll try.