duggulous
duggulous

Reputation: 2737

How can I bind other components besides ContentControl to a view in Caliburn Micro?

So in Caliburn Micro, I have been using the following method to compose a view inside of another view:

  1. Put a ContentControl inside the composing View.
  2. Create a property on the composing ViewModel, and assign to it the composed ViewModel
  3. Give the ContentControl a x:Name attribute that matches the name of the composed ViewModel property on the composing ViewModel.

like so...

View:

<UserControl x:Class="MyProject.MyComposingView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008">

    <ContentControl x:Name="MyComposedViewModel"/>

</UserControl>

ViewModel:

class ComposingViewModel : PropertyChangedBase
{
    private ComposedViewModel _myComposedViewModel;
    public ComposedViewModel MyComposedViewModel
    {
        get { return _myComposedViewModel; }
        set
        {
            _myComposedViewModel= value;
            NotifyOfPropertyChange(() => Page);
        }
    }

    public ComposingViewModel(ComposedViewModel myComposedViewModel)
    {
        MyComposedViewModel = myComposedViewModel;
    }
}

Caliburn Micro automagically figures out that because it's a ContentControl it obviously doesn't want to bind to a ViewModel, but rather to its associated View, and so it does something under the hood to bind the ContentControl's Content property to MyComposedView instead of MyComposedViewModel.

But, what if I don't want to use a ContentControl? Like, maybe some reusable custom component of mine that wraps a ContentControl instead? For example:

<UserControl x:Class="MyProject.MyContentWrapper"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d">
    <Grid x:Name="PreviewBox" SizeChanged="onSizeChanged">
        <Image x:Name="BGImage" Source="{Binding BGImage}"/>    
        <ContentControl Content="{Binding}"/>   
    </Grid>
</UserControl>

If I replace the ContentControl with a MyContentWrapper, CaliburnMicro no longer works its magic to supply MyComposedView, and I end up with a TextBlock that says, MyProject.MyComposedViewModel.

How can I get CaliburnMicro to know this is a situation where it should supply the View rather than the ViewModel?

Upvotes: 1

Views: 341

Answers (1)

Frank
Frank

Reputation: 4481

What you want to do is add a convention for your custom control:

  1. Go to the code for ConventionMananger on github.
  2. Search for AddElementConvention<ContentControl>.
  3. Create a new method in your Bootstrapper that runs when your application starts. Add a call to ConventionManager.AddElementConvention<YourControl> similar to the one for ContentControl.
  4. Make sure to put a ContentPropertyAttribute on your control and specify the content property.

Disclaimer: I'm on mobile and can't validate this.

Upvotes: 0

Related Questions