3

I'm having some trouble with loading a view into a ContentControl. I'm trying to keep this as simple as possible so I used the Hello project that comes with CM. I made sure that the Hello project compiles correctly, and runs. It displays a window with a textbox, and a button. Both the textbox and button are wired at runtime to the sample ViewModel.

I modified the ShellView.xaml and replaced the StackPanel control with the Grid control, and setup the grid with 4 rows and a single column. I assigned the textbox to the first row, the button to the second row, and then two separate ContentControl to the final two rows.

<Grid Width="800" Height="600">
    <Grid.ColumnDefinitions>
        <ColumnDefinition></ColumnDefinition>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition></RowDefinition>
        <RowDefinition></RowDefinition>
        <RowDefinition></RowDefinition>
        <RowDefinition></RowDefinition>
    </Grid.RowDefinitions>
    <TextBox Grid.Row="0" Grid.Column="0" x:Name="Name" />
    <Button Grid.Row="1" Grid.Column="0" x:Name="SayHello" Content="Click Me" />
<ContentControl Grid.Row="2" Grid.Column="0" x:Name="TopMenu" 
    VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch"></ContentControl>
<ContentControl Grid.Row="3" Grid.Column="0" x:Name="BottomMenu" 
    VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch"></ContentControl>
</Grid>

I created two separate C# classes in the ViewModels folder which are the ViewModels and are respectively called TopMenuViewModel.cs, and BottomMenuViewModel.cs. Both classes extend the PropertyChangedBase class. This is simply mimicking the ShellViewModel.cs class that comes with the sample project.

using System;
using Caliburn.Micro;
namespace TestWithCaliburnMicro.ViewModels
{
/// <summary>
/// Description of BottomMenuViewModel.
/// </summary>
public class BottomMenuViewModel : PropertyChangedBase
{
    public BottomMenuViewModel()
    {
    }

}

I created two separate WPF User Controls in the Views folder which are the corresponding View and are respectively called TopMenuView.xaml and BottomMenuView.xaml. I added a Label in each xaml with the Content of "Top Menu" or "Bottom Menu" to differentiate between the two.

<Grid>
    <Label>Bottom Menu View</Label>
</Grid>

In the ShellViewModel.cs class I created two public properties with only the "get" accessor set to return an instance of the corresponding ViewModel.

    private BottomMenuViewModel _bottomMenu;
    public BottomMenuViewModel BottomMenu {
        get { return _bottomMenu; }
    }

    private TopMenuViewModel _topMenu;
    public TopMenuViewModel TopMenu {
        get { return _topMenu;} 
    }

Adding a break to the get accessor of either property shows that the get accessor is called when debugging the project. I added a simple statement to the constructor of the BottomMenuViewModel.cs class, such as int x = 0 and added a break to that line, but the break is never hit which to me means that the constructor is not called, so really the class is not created?

I believe what I'm doing is exceptionally basic and have read the All About Conventions document on the CM Codeplex site, and confirmed the logic with this comment: Prior question on stackoverflow

Hopefully someone will have the time to read this and point me in the right direction. Thanks.

Solution on GitHub. Note: made with SharpDevelop 4.x GitHub solution

Community
  • 1
  • 1
voidmain
  • 1,521
  • 1
  • 12
  • 14
  • can you put the solution up on github and I'll grab it and look through it. – Mark W Jun 18 '12 at 16:26
  • Where do you set `_topMenu`, and `_topMenu`? Because Caliburn won't create ViewModels for you. It has two modes: ViewModel first then it will create a view for viewmodel OR View first when you create the View and also the ViewModel and caliburn just glue them together. – nemesv Jun 18 '12 at 17:20
  • @nemesv: Good point. I was following convention of supplying only the get accessor as based on the sample HelloScreens project located here: [link](http://caliburnmicro.codeplex.com/wikipage?title=Screens%2c%20Conductors%20and%20Composition&referringTitle=Documentation) and also HelloScreensWPF located here: [link](https://skydrive.live.com/?cid=5f154148de0c0da9#) which show the use of a get accessor alone to show a View. `readonly IDialogManager dialogs; public IDialogManager Dialogs { get { return dialogs; } }` – voidmain Jun 18 '12 at 17:40
  • you need to set the ViewModels in the constructor of the MainViewModel or the ShellViewModel (if you're using that). – Mark W Jun 18 '12 at 17:50
  • Thanks to Mark W and nemesv for your assistance. The Views are now loaded and wired to the ViewModels using your clues about setting the Views and from the technique in this answer: [link](http://stackoverflow.com/a/7881066)In my case I modified the constructor of ShellViewModel as follows: `public ShellViewModel() { this.BottomMenu = new BottomMenuViewModel(); }` As suggested I also added a set accessor to the properties used to load the Views. `public BottomMenuViewModel BottomMenu { get { return _bottomMenu; } set { _bottomMenu = value; } } ` – voidmain Jun 18 '12 at 19:00

1 Answers1

0

Either instantiate your view models in the constructor of the ShellViewModel, or if you wish to instantiate them at a later point, then add setters to your view model properties, and call the NotifyOfPropertyChange method to notify your UI that those property references have changed.

devdigital
  • 34,151
  • 9
  • 98
  • 120