使用 Microsoft.Toolkit.Mvvm 和 Microsoft.Xaml.Behaviors.Wpf 将事件参数传递给命令
Pass event argument to command with Microsoft.Toolkit.Mvvm and Microsoft.Xaml.Behaviors.Wpf
我尝试为 this sample (just simple paging part) with Microsoft.Toolkit.Mvvm 实现 MVVM 模式,不幸的是,我失败了 :( 因为我在 WPF 中也是 MVVM :))
主要问题是如何通过 InvokeCommandAction (Microsoft.Xaml.Behaviors.Wpf) 将事件参数传递给命令?我认为文档和 wiki 有限...
在这种情况下,我在 MainWindow.xaml 中更改此代码:
...
<ui:Frame x:Name="ContentFrame" Navigated="ContentFrame_Navigated" />
</ui:NavigationView>
至:
...
<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>
并将与此事件相关的代码从 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());
}
}
到 MainWindowViewModel.cs 并将其更改为:
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());
}
}
或者试试这个:
public MainWindowViewModel()
{
ContentFrame_NavigatedCommand = new RelayCommand<NavigationEventArgs>(ContentFrame_Navigated);
}
...
private void ContentFrame_Navigated(NavigationEventArgs e)
{
...
}
在调试模式下,“ContentFrame_Navigated”根本不会触发,“ContentFrame_NavigatedCommand”仅在启动时触发一次(此时“NavigationViewVM”为空!)
我忽略了一个明显的问题,不是吗?
另外,这可能是重复的,对此我很抱歉,但我已经尝试阅读所有类似的问题并参考了好几天!
感谢 Jesse 的评论...我编辑了那部分代码,但主要问题是 ItemInvoked 事件根本没有实现!但是,我决定改为实施 SelectionChanged 事件:
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>
...
在MainWindowViewModel.cs中:
private void NavVM_SelectionChanged(NavigationViewSelectionChangedEventArgs args)
{
if (args.IsSettingsSelected)
{
Navigate(typeof(Views.Pages.SettingsPage));
}
else
{
var selectedItem = (NavigationViewItem)args.SelectedItem;
Navigate(selectedItem);
}
}
我尝试为 this sample (just simple paging part) with Microsoft.Toolkit.Mvvm 实现 MVVM 模式,不幸的是,我失败了 :( 因为我在 WPF 中也是 MVVM :))
主要问题是如何通过 InvokeCommandAction (Microsoft.Xaml.Behaviors.Wpf) 将事件参数传递给命令?我认为文档和 wiki 有限... 在这种情况下,我在 MainWindow.xaml 中更改此代码:
...
<ui:Frame x:Name="ContentFrame" Navigated="ContentFrame_Navigated" />
</ui:NavigationView>
至:
...
<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>
并将与此事件相关的代码从 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());
}
}
到 MainWindowViewModel.cs 并将其更改为:
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());
}
}
或者试试这个:
public MainWindowViewModel()
{
ContentFrame_NavigatedCommand = new RelayCommand<NavigationEventArgs>(ContentFrame_Navigated);
}
...
private void ContentFrame_Navigated(NavigationEventArgs e)
{
...
}
在调试模式下,“ContentFrame_Navigated”根本不会触发,“ContentFrame_NavigatedCommand”仅在启动时触发一次(此时“NavigationViewVM”为空!)
我忽略了一个明显的问题,不是吗? 另外,这可能是重复的,对此我很抱歉,但我已经尝试阅读所有类似的问题并参考了好几天!
感谢 Jesse 的评论...我编辑了那部分代码,但主要问题是 ItemInvoked 事件根本没有实现!但是,我决定改为实施 SelectionChanged 事件: 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>
...
在MainWindowViewModel.cs中:
private void NavVM_SelectionChanged(NavigationViewSelectionChangedEventArgs args)
{
if (args.IsSettingsSelected)
{
Navigate(typeof(Views.Pages.SettingsPage));
}
else
{
var selectedItem = (NavigationViewItem)args.SelectedItem;
Navigate(selectedItem);
}
}