WPF Caliburn.Micro: Trouble with MenuBar UserControl and ViewModels

34 views Asked by At

I'm developing a WPF application using the Caliburn.Micro framework. In my application, I have a ShellView (Window) named ShellWindow along with its associated ShellViewModel. Inside this window, I'd like to have a navigation bar (MenuBar) placed in a separate UserControl with its own ViewModel (MenuBarView and MenuBarViewModel).

Additionally, I have two other UserControls named Tab1 and Tab2. The problem I'm encountering is that when I click on Tab2, the application searches for the method in the ShellViewModel instead of the expected behavior, which should be searching in the MenuBarViewModel. Moreover, the DataContext is not being set as expected due to Caliburn conventions.

Furthermore, when I click on Tab1, I expect the content within the ShellView to change accordingly. Currently, this behavior is not occurring as expected.

I've organized my folder structure with "Views" and "ViewModels," and I've ensured that naming, x:Class, and namespaces are set correctly. The purpose of outsourcing the MenuBar is to keep the application modular, but if I have to include the logic in the ShellWindow, it defeats the purpose.

Can anyone help me understand why Caliburn.Micro is not finding the correct ViewModel for the MenuBar UserControl, why the DataContext isn't being set as expected, and how to achieve the desired content-changing behavior when clicking on Tab1?

ShellView && ShellViewModel

 <Window x:Class="CaliTest.Frontend.Views.ShellView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:cm="http://caliburnmicro.com"
    xmlns:views="clr-namespace:CaliTest.Frontend.Views"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800">
<Grid>
    <DockPanel>
        <views:MenuBarView DockPanel.Dock="Top" />
        <ContentControl cm:View.Model="{Binding ActiveItem}" />
    </DockPanel>
</Grid>
namespace CaliTest.Frontend.ViewModels;

public class ShellViewModel : Conductor<Screen>
{
public ShellViewModel()
{
    Tab1ViewModel = new Tab1ViewModel();
    Tab2ViewModel = new Tab2ViewModel();
}

public Tab1ViewModel Tab1ViewModel { get; private set; }
public Tab2ViewModel Tab2ViewModel { get; private set; }

protected override async Task OnActivateAsync(CancellationToken cancellationToken)
{
    await ActivateItemAsync(Tab1ViewModel, cancellationToken);
}
}

MenuBarView && MenuBarViewModel

<UserControl x:Class="CaliTest.Frontend.Views.MenuBarView"
         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:cm="http://caliburnmicro.com"
         mc:Ignorable="d"
         d:DesignHeight="300" d:DesignWidth="300">
<Grid>
    <Menu>
        <MenuItem Header="Tab 1" cm:Message.Attach="[Event Click] = [Action LoadTab1]"/>
        <MenuItem Header="Tab 2" cm:Message.Attach="[Event Click] = [Action LoadTab2]"/>
    </Menu>
</Grid>
namespace CaliTest.Frontend.ViewModels;

public class MenuBarViewModel : Screen
{
private readonly ShellViewModel _shellViewModel;

public MenuBarViewModel(ShellViewModel shellViewModel)
{
    _shellViewModel = shellViewModel;
}

public async Task LoadTab1()
{
    await _shellViewModel.ActivateItemAsync(_shellViewModel.Tab1ViewModel);
}

public async Task LoadTab2()
{
    await _shellViewModel.ActivateItemAsync(_shellViewModel.Tab2ViewModel);
}

Tab1

public class Tab1ViewModel : Screen
{
  public Tab1ViewModel()
  {
    
  }
}

I have attempted the following steps to resolve my issue:

Verified that my folder structure, naming, x:Class, and namespaces for the Views and ViewModels are correctly set up according to Caliburn.Micro conventions.

Checked that the MenuBar UserControl (MenuBarView) and its associated ViewModel (MenuBarViewModel) are correctly implemented and named.

Ensured that the event handling or bindings for the Tab1 and Tab2 UserControls are correctly set up in the ShellView.

What were you expecting:

I expected the following outcomes:

When clicking on Tab2, I expected the application to search for the method in the MenuBarViewModel instead of the ShellViewModel, as Tab2 is part of the MenuBar.

I anticipated that the DataContext would be set correctly according to Caliburn conventions for the MenuBar UserControl (MenuBarView and MenuBarViewModel).

When clicking on Tab1, I expected the content within the ShellView to change to reflect the content associated with Tab1, but this behavior is not occurring as expected.

0

There are 0 answers