microsoft / microsoft-ui-xaml

Windows UI Library: the latest Windows 10 native controls and Fluent styles for your applications
MIT License
6.28k stars 675 forks source link

WinUI 3 NavigationView ignores SelectedItem Binding #2691

Open spydacarnage opened 4 years ago

spydacarnage commented 4 years ago

I'm fairly new to UWP development, so it's possible that I could be missing something, but I couldn't find anything from an internet search...

I have a WinUI 3 NavigationView and in it, the SelectedItem property is set to "{Binding SelectedMenuItem}", where SelectedMenuItem is stored in a view model class assigned to the DataContext. When a menu item is clicked, it fires a SelectionChanged event which tells a Frame to navigate to a new page, and when that Frame fires its Navigated event, I set the SelectedMenuItem property (and raise a PropertyChanged event).

At first, everything seemed to be working, because I was clicking the menu items to make things change. However, when I implemented the back button, the same process occurs - the Frame is told to GoBack, it fires the Navigated event, and the SelectedMenuItem property is updated. However, the previously pressed menu item is still selected, and nothing can seem to change that other than clicking another one.

However, if I use extra buttons (not in the NavigationView.MenuItems list) to tell the Frame to navigate, the selected item does change when the Frame_Navigated event sets the SelectedMenuItem property, both navigating forwards, and when the back button is pressed. UNTIL... I use the NavigationView menu, at which point all of that stops working and the clicked item always overrides the Binding property.

Am I doing something wrong?

StephenLPeters commented 4 years ago

@ojhad FYI

StephenLPeters commented 4 years ago

@spydacarnage is this issue unique to winui 3 or does it repro with winui 2 as well?

spydacarnage commented 4 years ago

It seems to be doing it in a Blank App (Universal Windows) project (which I assume is WinUI 2?)

After more testing, it looks like using x:Bind instead of Binding gets around the problem (in both WinUI 3 and the above project type), but this means, if I'm reading documentation correctly, that x:Bind only binds to a Page's Code Behind class, not the DataContext, making MVVM much more difficult to work with?

On Tue, 16 Jun 2020 at 21:05, Stephen L Peters notifications@github.com wrote:

@spydacarnage https://github.com/spydacarnage is this issue unique to winui 3 or does it repro with winui 2 as well?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/microsoft/microsoft-ui-xaml/issues/2691#issuecomment-644984244, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADIEDQP2ZQZQJXCUQGTAFD3RW7GA7ANCNFSM4N7ZYUDQ .

ranjeshj commented 4 years ago

I suspect this is by design. @MikeHillberg and @fabiant3 as FYI

MikeHillberg commented 4 years ago

In addition to raising the property changed event, are you setting the binding to OneWay? {Binding SelectedMenuItem, Mode=OneWay}

Since there's perf overhead with listening to change notifications, Binding mode defaults to OneTime.

About Binding vs x:Bind, a common pattern is for the Page or UserControl class to have a ViewModel property. So you have {x:Bind ViewModel.SelectedMenuItem}

spydacarnage commented 4 years ago

Yes, I was setting the Mode to OneWay.

I have noticed the ViewModel property approach and am now using that. Thanks.

On Tue, 23 Jun 2020, 21:55 MikeHillberg, notifications@github.com wrote:

In addition to raising the property changed event, are you setting the binding to OneWay? {Binding SelectedMenuItem, Mode=OneWay}

Since there's perf overhead with listening to change notifications, Binding mode defaults to OneTime.

About Binding vs x:Bind, a common pattern is for the Page or UserControl class to have a ViewModel property. So you have {x:Bind ViewModel.SelectedMenuItem}

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/microsoft/microsoft-ui-xaml/issues/2691#issuecomment-648413022, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADIEDQN2J7C26DPJMHVKR43RYEJFRANCNFSM4N7ZYUDQ .

atiyka commented 3 years ago

I can confirm, that the Binding to the SelectedItem property of a NavigationView is not working. I have a WPF app and I'm using XamlIslands to add UWP components to the app. I tried the x:Bind, how @MikeHillberg said and with this it works fine.

MikeHillberg commented 3 years ago

I don't understand the app code well enough to debug the {Binding} case, but glad the {x:Bind} works. In the Xaml Islands case I don't believe the WPF DataContext flows through to become the island's DataContext. And generally the WPF {Binding} and Xaml {Binding} are two different things. But {x:Bind} is just generating code-behind, so behaving like any other C# code-behind.

oliverw commented 1 year ago

Doesn't work reliably, not even using x:Bind.

eduardoagr commented 1 year ago

is very frustrating when you want to use winUI and you realize this issue.

eduardoagr commented 1 year ago

The workaround that I found, is to send a message, from the viewMdel everytime the element changes.

` [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 for the view

` 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) {

            var tag = message.Tag.ToString();
            NavFrame.Navigate(PageTypeMapper.PageTypeDictionary[tag]);
        }
    }`

Please microsoft fix this