How to manually activate a view?

Sep 14, 2010 at 7:32 PM

I'm clear on the way CM operates automatically using a specific naming policy,and I have a ShellView with the following
ContentControl x:Name="ActiveItem"  />
that shows a ViewModel1 and View1 just fine.

But I was wondering how to do this manually.
I was thinking something like this would work, but it doesn't
<ContentControl x:Name="Foo" cal:View.Model="{Binding Path=ViewModel1}" />

The reason I'm asking is because if my ShellViewModel is thus
ShellViewModel : Conductor<IScreen>.Collection.OneActive

I'd like to attach various screens to different places in the shell, and I'm not sure how its done.




Sep 14, 2010 at 8:03 PM

Assuming you have a property on the DataContext named ViewModel1 then <ContentControl x:Name="Foo" cal:View.Model="{Binding Path=ViewModel1}" /> should work.

Sep 14, 2010 at 9:31 PM

Thanks, and I do/did not have a DataContext property and I assume you mean a DataContext on View1.
But I don't seem to be able to make it work.

Perhaps I'm going in the wrong direction.

If the ShellViewModel has multiple screens, what would be your advice for attaching them to various controls.
I'm still in Prism RegionAdapter thinking mode!!


Sep 14, 2010 at 10:59 PM

I've done what I was trying to do in code,

 //In ShellViewModel
       protected override void OnInitialize()

            var v = this.GetView(null); //get the view for the ShellViewModel
            var w = v as Window;  
            var cc = w.FindName("Foo") as DependencyObject; //Find the control with Foo as name
            if (cc != null)
                //instantiate ViewModel1 and View1
                ViewModel1 viewmodel = IoC.Get<ViewModel1>();
                var view = ViewLocator.LocateForModel(viewmodel, cc, null);
                ViewModelBinder.Bind(viewmodel, view, null);

                //I made this method Public in library (can you update Caliburn Micro?)
                View.SetContentProperty(cc, view);


But there must be a better way?


Sep 15, 2010 at 2:22 AM

You are definitely going about this the wrong way :) Can you put together a small solution and email it to me. I will fix it and send it back to you. email me at robertheisenberg at hotmail dot com

Sep 16, 2010 at 5:17 PM


would it be possible to post the solution? Or, more in general, what's the right approach in CM to obtain the same effect as regions in PRISM? Is there any post on the topic? 



Sep 16, 2010 at 5:28 PM

Have a read through this: Pay particular attention to the section at the beginning where it discusses attached properties. You will want to have a look at the View.Model attached property which can be placed on any control with Content property. This allows you to bind in view models along with their corresponding views. By using this in combination with a Conductor, you can achieve nice dynamic, composite UIs. I haven't written the article on conductors yet. It's next on the list.

Sep 18, 2010 at 5:16 PM

I was trying to solve the problem I believe the OP had during the week. Got it down last night with the help of this thread and a few others. Using this approach you can have multiple ContentPresenters within your shell view and switch which sub-viewmodel they display and Caliburn.Micro will not only bind the correct view, but also retain the view so when you switch back and forth, controls are still all in the place they were left even if unbound.

Shell View:-

<UserControl x:Class="SLPlayingApp.ShellView"

    <Grid x:Name="LayoutRoot" Background="White">
            <StackPanel Orientation="Horizontal">
                <Button x:Name="ShowFoo" Content="Show Foo" Margin="6,6" />
                <Button x:Name="ShowBar" Content="Show Bar" Margin="6,6" />

            <ContentControl x:Name="this_can_be_anything" Margin="14,14" cal:View.Model="{Binding Path=SubVM}">
                <TextBlock>Content will replace this</TextBlock>


Shell ViewModel class (no need to inherit from and of the screenconductor stuff, although if you have a scenario where you need to manage lifetimes and activations you should look into it rather than following this example otherwise you're likely to just reinvent what's already there).

    public class ShellViewModel : PropertyChangedBase
        FooViewModel _foo = new FooViewModel();
        BarViewModel _bar = new BarViewModel();
        object _subVM;
        public object SubVM
            get { return _subVM; }

        public void ShowFoo()
            _subVM = _foo;

        public void ShowBar()
            _subVM = _bar;

Obviously I'm a bad person here because I'm newing up the Foo and Bar viewmodels instead of injecting them  - so shoot me :) I haven't shown them here, but FooViewModel and BarViewModel are just classes that derive from PropertyChangedBase. The corresponding FooView and BarView are ordinary UserControls that Caliburn.Micro will instantiate and bind the same was as it does the ShellView.

It's the cal:View.Model="{Binding Path=SubVM}" attached property on the ContentPresenter that makes it work - the binding path points to the propert of the ShellViewModel instead of the x:Name with the others. The View.Model attached property causes a global event handler to be attached which does the view creation/caching and binding when the value of ShellViewModel.SubVM changes.

Sep 19, 2010 at 8:06 PM

I have to offer my thanks to Rob for the example of how to use Caliburn Micro to bind a View/ViewModel in a separate Module into a place in Shell. This was the underlying thing I was trying to do, but where I thought I needed to do it manually. But Rob's example shows how simple it is to get CM to do it for you using the naming convention fundamental to CM.

I thought the concept is so good that I've blogged about it and provided an example here.

So that should please Riccardo, and thanks Richard for your contribution. Your forgiven in not using MEF - it is a quick example!! But your solution is similar to Rob's only differing by having a button to select which module you want. I think I will add your idea into my Demo, because I think you might be able to get rid of cal:View.Model and use the x:Name property instead.

I'm impressed by CM and look forward to discovering more about its capablities.