1

I'd like to reuse a view for 2 different viewmodels, in my example MyEntityEditViewModel and MyEntityCreateViewModel. The view is basically just a form with a Save button, so pretty common layout.

I created both view models along with a parent view / view model (MyEntitySummaryViewModel) and now I'd like to define the form view using a ContentControl.

Summary view:

<ContentControl x:Name="ActiveItem" cal:View.Model="{Binding ActiveItem}" cal:View.Context="MyEntityDetailView" />

MyEntitySummaryViewModel:

public MyEntity SelectedEntity {
    get { return _selectedEntity; }
    set {
        _selectedEntity = value;
        NotifyOfPropertyChange();

        ActivateItem(new MyEntityEditViewModel(_selectedEntitity));
    }
}

public void Create() {
    ActivateItem(new MyEntityCreateViewModel(new MyEntity()));
}

My problem is now that Caliburn tries to locate a 'MyEntityEditView' due to it's view locating conventions, even if I strictly defined the context of the ContentControl as a custom view. Is there a way around this? Or am I doing something completely wrong here?

artganify
  • 683
  • 1
  • 8
  • 23
  • Never tried caliburn, but there are [data templates](http://stackoverflow.com/a/19865031/1997232) to assign view. Assign same view to both viewmodels. – Sinatr Oct 22 '15 at 10:24
  • in that case not required two view model. craete one view model or one partial view for it and after that render that partial view on createview or editview.. – Pankaj Gupta Oct 22 '15 at 10:28
  • @Sinatr Thanks, but my foundation is CM. I'm considering working around the framework when there is no other solution to this. :) – artganify Oct 22 '15 at 10:30
  • @PankajGupta Partial views? In WPF? Well I could technically 'simulate' them by creating an extra view/viewmodel as a wrapper, but I hope there's a solution with less overhead. =) – artganify Oct 22 '15 at 10:31

2 Answers2

0

If my understanding is right, You want 2 type of ViewModel to point on the same view. If so juste create a base classe for your Entity (EntityBaseViewModel) and Create a View (EntityBaseView).

To Bind a ContentControl set his x:Name so the name match a Property of your ViewModel.

Example:

View (ShellView):

<ContentControl x:Name="SelectedEntity"/>

ViewModel (ShellViewModel):

public EntityBaseViewModel  SelectedEntity 
{
    get 
    { 
        return this._selectedEntity; 
    }
    set 
    {
        this._selectedEntity = value;
        this.NotifyOfPropertyChange(() => SelectedEntity);
    }
}

And Caliburn will find the View for the ViewModel and bind the DataContext if you did create your ViewModel / View along the naming convention like you said.

C1rdec
  • 1,647
  • 1
  • 21
  • 46
0

A little late to the party, but perhaps this will help someone. This video helped a lot for me - (Tim Corey, WPF and Caliburn with MVVM)

Setting up the ShellView with a control that points to ActiveItem as you mentioned, allows that control to display whatever view you tell it from the ShellViewModel code. I was also using Fody with this project, so that took care of the change notifications so you won't see those listed in code.

ShellView -

<Button x:Name="LoadMainPage" />    
<Button x:Name="LoadSecondPage" />
<ContentControl x:Name="ActiveItem"/>

The ShellViewModel -

public class ShellViewModel : Conductor<object>.Collection.OneActive
{       
        public MainPageViewModel MainPageVM = new MainPageViewModel();
        public SecondPageViewModel SecondPageVM = new SecondPageViewModel();

        public ShellViewModel()
        {           
            LoadMainPage(); // auto load main page on startup
        }

        public void LoadMainPage()
        {
            ActivateItem(MainPageVM);
        }

        public void LoadSecondPage()
        {
            ActivateItem(SecondPageVM);
        }
}

Instead of creating a new instance of a ViewModel when using ActivateItem, you're just re-using the initial ones created. Or, if you DO prefer to create another instance each time that particular view is launched, then simply use the ActivateItem as you already have.

In your SecondPageViewModel for the view, which will occupy the space in the ContentControl for ActiveItem -

public class SecondPageViewModel : Screen

SecondPageView.xaml added as a User Control (and any other sub/child views you want to create) -

<UserControl x:Class="MyNamespace.Views.SecondPageView"
             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" 
             xmlns:local="clr-namespace:MyNamespace.Views"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>

    </Grid>
</UserControl>

This will allow you to flip back and forth between whatever views you want from a base view/viewmodel, and display the contents of the child views (however many you want) that you choose within the ContentControl box.