threefx
threefx

Reputation: 81

Pass event argument to command with Microsoft.Toolkit.Mvvm and Microsoft.Xaml.Behaviors.Wpf

I try to implement the MVVM pattern for this sample (just simple paging part) with Microsoft.Toolkit.Mvvm unfortunately, I failed :( because I'm so noob in WPF also MVVM :))

the primary problem is how can I pass an argument of an event to command with InvokeCommandAction (Microsoft.Xaml.Behaviors.Wpf)? there is limited documentation and wiki I think... in this scenario, I change this code in MainWindow.xaml :

...
        <ui:Frame x:Name="ContentFrame" Navigated="ContentFrame_Navigated" />
    </ui:NavigationView>

to :

            ...
<ui:Frame x:Name="ContentFrame" DataContext="{Binding ContentFrameVM}">
            <i:Interaction.Triggers>
                <!--  Events  -->
                <i:EventTrigger EventName="Navigated">
                    <i:InvokeCommandAction Command="{Binding ContentFrame_NavigatedCommand}" PassEventArgsToCommand="True"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </ui:Frame>

and move the code related to this event from MainWindow.xaml.cs :

        private void ContentFrame_Navigated(object sender, NavigationEventArgs e)
    {
        if (e.SourcePageType() == typeof(SettingsPage))
        {
            NavView.SelectedItem = NavView.SettingsItem;
        }
        else
        {
            NavView.SelectedItem = NavView.MenuItems.OfType<NavigationViewItem>().FirstOrDefault(x => GetPageType(x) == e.SourcePageType());
        }
    }

to MainWindowViewModel.cs and change it to :

   class MainWindowViewModel : ObservableObject
  {
  public IRelayCommand ContentFrame_NavigatedCommand { get; }
  private NavigationView _navigationViewVM;
    public NavigationView NavigationViewVM
    {
        get => _navigationViewVM;
        set => SetProperty(ref _navigationViewVM, value);
    }

    private ModernWpf.Controls.Frame _contentFrameVM;
    public ModernWpf.Controls.Frame ContentFrameVM
    {
        get => _contentFrameVM;
        set => SetProperty(ref _contentFrameVM, value);
    }

    public MainWindowViewModel()
    {
        ContentFrame_NavigatedCommand = new RelayCommand<object>(ContentFrame_Navigated, (o) => { return true; });
    }
    ...

    private void ContentFrame_Navigated(object o)
    {
        NavigationEventArgs e = o as NavigationEventArgs;
        if (e.SourcePageType() == typeof(Views.Pages.SettingsPage))
        {
            NavigationViewVM.SelectedItem = NavigationViewVM.SettingsItem;
        }
        else
        {
            NavigationViewVM.SelectedItem = NavigationViewVM.MenuItems.OfType<NavigationViewItem>().FirstOrDefault(x => GetPageType(x) == e.SourcePageType());
        }
    }

or try this :

public MainWindowViewModel()
    {
        ContentFrame_NavigatedCommand = new RelayCommand<NavigationEventArgs>(ContentFrame_Navigated);
    }
...
private void ContentFrame_Navigated(NavigationEventArgs e)
    {
        ...
    }

in debug mode "ContentFrame_Navigated" doesn't fire at all and "ContentFrame_NavigatedCommand" just triggered once at startup (in that time "NavigationViewVM" is null!)

I'm ignoring an obvious issue Isn't that so? also, it's a Possible duplicate sorry about that but I tried to read all similar questions and ref for days!

Upvotes: 3

Views: 5425

Answers (1)

threefx
threefx

Reputation: 81

Thanks to Jesse's comment... I edit that part of the code but the main problem was ItemInvoked event was not implemented at all! however, I decide to implement SelectionChanged event instead: MainWindow.xaml :

<ui:NavigationView>
<i:Interaction.Triggers>
            <i:EventTrigger EventName="SelectionChanged" SourceObject="{Binding ElementName=NavView}">
                <i:InvokeCommandAction Command="{Binding NavVM_SelectionChangedCommand}" PassEventArgsToCommand="True"/>
            </i:EventTrigger>
  </i:Interaction.Triggers>
   ...

in MainWindowViewModel.cs:

 private void NavVM_SelectionChanged(NavigationViewSelectionChangedEventArgs args)
    {
        if (args.IsSettingsSelected)
        {
            Navigate(typeof(Views.Pages.SettingsPage));
        }
        else
        {
            var selectedItem = (NavigationViewItem)args.SelectedItem;
            Navigate(selectedItem);
        }
    }

Upvotes: 4

Related Questions