I have a window that contains a Viewbox. In that Viewbox, I would like to have one of several views which I have already created as UserControls. I am using the MVVM (Model View View-Model) design pattern. I have searched for about an hour online, and I cannot find any examples or tutorials that explain how to display a UserControl using a ContentPresenter
.
Depends.
I think your main issue is that a ContentPresenter
is only used within a control template. You can't just stick it in a Window and expect it to show the content of the window. I believe what you really need to do is to use a ContentControl to host your UI.
By binding your model to the Content
property of this control, you can set up DataTemplates that contain the expected view for that model. I'll give you an abbreviated example. Note, this may not match your design, but it demonstrates how it all goes together.
First, for each view, create a Model (or ViewModel) which manages the data (and interaction) for that view.
public sealed class Dialog : INotifyPropertyChanged // or DependencyObject
{
public string Input {get;set;} // INPC or DP implementation not shown
public ICommand Cancel {get;set;}
// class definition not shown
}
Next, define your View to be shown in the ContentPresenter
<UserControl x:Class="Herp.DialogView"
HideImplementationDetails="true">
<Border BorderBrush="Red" BorderThickness="5">
<TextBlock Text="{Binding Input}" />
<Button Command="{Binding Cancel}">Cancel</Button>
<!-- etc etc -->
</Border>
</UserControl>
Next, in your window, add the ContentControl and the DataTemplate
<Window HideImplementationDetailsForBrevityOfXaml="true">
<Window.Resources>
<DataTemplate xmlns:t="clr-namespace:Herp"
DataType="{x:Type t:Dialog}">
<t:DialogView />
</DataTempalte>
</Window.Resources>
<ContentControl Content="{Binding}" />
</Window>
And finally set the DataContext of the Window to your Dialog
model.
public MyWindow()
{
InitializeComponent();
DataContext = new Dialog();
}
This is how the logic flows:
ContentControl
searches resources for a DataTemplate
whose DataType
is set to typeof(Dialog)
ContentControl
Any time the Content
of the ContentControl
changes, the same process repeats. So you can have many different models, each with a different DataTemplate containing a different UserControl, and every time you update the binding on the ContentControl you see the expected View.
With MVVM, you would bind a property of your ViewModel to the Content
property (call it Current or something), then switch out the model within the property to the expected value depending on the ViewModel's current state. Note, within a ContentControl, whatever is set to the Content
property becomes the DataContext
of the immediate child of the ContentControl. Similar to how each ItemsSource
within an ItemsControl
is the DataContext
of the visual tree defined within the ItemTemplate
.