使用Microsoft.Toolkit.Mvvm与Microsoft.Xaml.Behaviors.Wpf传递事件参数到命令
问题根因
- 绑定上下文匹配错误:你为
ui:Frame显式设置了DataContext="{Binding ContentFrameVM}",此时触发器内部的Command绑定默认会从ContentFrameVM(即你定义的ModernWpf.Controls.Frame类型属性)中查找ContentFrame_NavigatedCommand,但该命令实际定义在MainWindowViewModel中,绑定路径不匹配导致命令无法正常触发。 NavigationViewVM未赋值:你没有将视图层的NavigationView实例赋值给ViewModel的NavigationViewVM属性,导致触发命令时该属性为null。
修复方案
1. 修改XAML绑定
移除Frame上多余的DataContext设置,调整命令绑定路径,让它能正确找到MainWindowViewModel中的命令:
<ui:Frame x:Name="ContentFrame"> <i:Interaction.Triggers> <i:EventTrigger EventName="Navigated"> <i:InvokeCommandAction Command="{Binding DataContext.ContentFrame_NavigatedCommand, RelativeSource={RelativeSource AncestorType=Window}}" PassEventArgsToCommand="True"/> </i:EventTrigger> </i:Interaction.Triggers> </ui:Frame>
2. 给NavigationViewVM赋值
在MainWindow.xaml.cs的构造方法中,将前台的NavigationView实例传递给ViewModel:
public MainWindow() { InitializeComponent(); var vm = new MainWindowViewModel(); // 假设你前台NavigationView的x:Name为NavView vm.NavigationViewVM = NavView; DataContext = vm; }
3. 优化命令实现
使用泛型RelayCommand<NavigationEventArgs>避免参数拆箱,同时增加判空逻辑防止启动时首次触发报错:
public IRelayCommand<NavigationEventArgs> ContentFrame_NavigatedCommand { get; } public MainWindowViewModel() { ContentFrame_NavigatedCommand = new RelayCommand<NavigationEventArgs>(ContentFrame_Navigated); } private void ContentFrame_Navigated(NavigationEventArgs e) { if (NavigationViewVM == null) return; if (e.SourcePageType() == typeof(Views.Pages.SettingsPage)) { NavigationViewVM.SelectedItem = NavigationViewVM.SettingsItem; } else { NavigationViewVM.SelectedItem = NavigationViewVM.MenuItems .OfType<NavigationViewItem>() .FirstOrDefault(x => GetPageType(x) == e.SourcePageType()); } }
额外优化建议
从MVVM规范角度来说,ViewModel不应该持有视图控件的引用,你可以将NavigationView的SelectedItem绑定到ViewModel中的一个属性,通过修改该属性来更新选中状态,完全不需要把NavigationView实例传入ViewModel。
内容的提问来源于stack exchange,提问作者threefx
相关产品推荐
相关产品推荐

