Help with frame navigation mvvm

Eduardo Gomez 4,156 Reputation points
2023-06-25T13:12:14.1066667+00:00

I have been trying to navigate with a frame and NavigationView, without success

I Install Microsoft mvvm toolkit and behaviors (to be able to respond from a view Model).

I thought it was going to be easy, just create a property to catch the selected item and a command, to navigate and pass the frame to the method

User's image

Selected Item is null (when I change)

   <NavigationView
        Background="{ThemeResource AcrylicBackgroundFillColorBaseBrush}"
        IsBackButtonVisible="Collapsed"
        IsSettingsVisible="False"
        PaneDisplayMode="LeftCompact"
        SelectedItem="{x:Bind ViewModel.SelectedItem}">

I found this, so apparently is bug (because I did this exact same thing in wpf and it work in the first attempt), I wanted to use WinUI 3, because is the evolution of wpf, and I think is mature enough

https://github.com/microsoft/microsoft-ui-xaml/issues/2691

So, I thought "If I want to use MVVM, and passing a frame to a command is not very good practice, why I don't send a message to the view when I change, and tell the view to navigate", that way the viemodel doesn't know anything about the view

So, I changed my VM a little

[ObservableObject]
    public partial class NavWindowViewModel {

        private NavigationViewItem _selectedItem;

        [RelayCommand]
        private void NavigateToPage(object obj) {

            var args = obj as NavigationViewSelectionChangedEventArgs;

            _selectedItem = args.SelectedItem as NavigationViewItem;

            if (_selectedItem != null) {

                // Send the selected item as a message
                WeakReferenceMessenger.Default.Send(_selectedItem);
            }
        }
    }
}

and my code behind

public sealed partial class NavWindow : Window {

        public NavWindowViewModel ViewModel { get; set; }

        public NavWindow(NavWindowViewModel viewModel) {
            InitializeComponent();

            ViewModel = viewModel;

            // Subscribe to the message
            WeakReferenceMessenger.Default.Register<NavigationViewItem>(this, HandleSelectedItemMessage);
        }

        private void HandleSelectedItemMessage(object recipient, NavigationViewItem message) {
            if (message != null && NavFrame != null) {
                NavFrame.Navigate(message.GetType());
            }
        }

User's image

User's image

as you can see neither the Frame nor the message are null

this is my view, just in case

 <NavigationView
        Background="{ThemeResource AcrylicBackgroundFillColorBaseBrush}"
        IsBackButtonVisible="Collapsed"
        IsSettingsVisible="False"
        PaneDisplayMode="LeftCompact">
        <Interactivity:Interaction.Behaviors>
            <Core:EventTriggerBehavior EventName="SelectionChanged">
                <Core:EventTriggerBehavior.Actions>
                    <Core:InvokeCommandAction Command="{x:Bind ViewModel.NavigateToPageCommand}" />
                </Core:EventTriggerBehavior.Actions>
            </Core:EventTriggerBehavior>
        </Interactivity:Interaction.Behaviors>
        <NavigationView.MenuItems>
            <NavigationViewItem
                Content="Manage class"
                Tag="ManageClassPage">
                <NavigationViewItem.Icon>
                    <BitmapIcon UriSource="ms-appx:///Icons/classroom.png" />
                </NavigationViewItem.Icon>
            </NavigationViewItem>
            <NavigationViewItem
                Content="Create meeting"
                Tag="CreateMeeting">
                <NavigationViewItem.Icon>
                    <BitmapIcon UriSource="ms-appx:///Icons/meeting.png" />
                </NavigationViewItem.Icon>
            </NavigationViewItem>
            <NavigationViewItem
                Content="Join meeting"
                Tag="CreateMeeting">
                <NavigationViewItem.Icon>
                    <BitmapIcon UriSource="ms-appx:///Icons/join.png" />
                </NavigationViewItem.Icon>
            </NavigationViewItem>
            <NavigationViewItem
                Content="Report card"
                Tag="ManageClassPage">
                <NavigationViewItem.Icon>
                    <BitmapIcon UriSource="ms-appx:///Icons/report-card.png" />
                </NavigationViewItem.Icon>
            </NavigationViewItem>
            <NavigationViewItem
                Content="Schedule exam"
                Tag="ManageClassPage">
                <NavigationViewItem.Icon>
                    <BitmapIcon UriSource="ms-appx:///Icons/Schedule.png" />
                </NavigationViewItem.Icon>
            </NavigationViewItem>
        </NavigationView.MenuItems>

        <Frame x:Name="NavFrame" Background="Blue" />

    </NavigationView>
</Window>

my dependency injection

 public partial class App : Application {

        private IHost _host;

        public App() {
            InitializeComponent();
        }

        protected override void OnLaunched(LaunchActivatedEventArgs args) {
            _host = Host.CreateDefaultBuilder()
                .ConfigureServices(ConfigureServices)
                .Build();

            // Start the host
            _host.Start();

            // Resolve and activate the main window using dependency injection
            var mainWindow = _host.Services.GetRequiredService<NavWindow>();
            mainWindow.Activate();
        }

        private void ConfigureServices(IServiceCollection services) {
            // Register your dependencies here
            services.AddTransient<Frame>();
            services.AddTransient<NavWindowViewModel>();
            services.AddTransient(provider => new NavWindow(provider.GetRequiredService<NavWindowViewModel>()));

            // Add other services as needed
        }
    }
}

repo: https://github.com/eduardoagr/Demy-AI

Windows development | Windows App SDK
{count} votes

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.