从用户控件调用ViewModel命令触发空引用异常,寻求解决方案
问题核心
你碰到的空引用异常,根源是_loginViewModel字段未被正确赋值。你的Login控件构造函数需要传入LoginViewModel实例,但实际实例化Login时,要么没传该参数,要么传入的是null,导致调用_loginViewModel.NavigateMM1Command.Execute(null)时触发异常。
解决方案
1. 正确传递LoginViewModel实例
LoginViewModel构造依赖的NavigationStore,应该是全局共享的实例(导航状态需要统一管理),所以不要在Login控件内部手动创建,要在更高层级(比如应用启动逻辑、主ViewModel或依赖注入容器)先初始化好NavigationStore和LoginViewModel,再传给Login控件。
示例代码:
// 全局初始化NavigationStore(应用启动时仅创建一次) var navigationStore = new NavigationStore(); // 创建LoginViewModel实例 var loginViewModel = new LoginViewModel(navigationStore); // 创建Login控件并传入ViewModel var loginView = new Login(loginViewModel); // 根据你的导航逻辑,将loginView设置为当前显示视图 navigationStore.CurrentViewModel = loginViewModel;
2. XAML声明Login控件的处理方式
如果Login控件是在XAML中直接声明的,要确保DataContext绑定的是已初始化的LoginViewModel。可以先把NavigationStore注册为全局单例资源:
<!-- 在App.xaml的Resources节点中添加 --> <local:NavigationStore x:Key="NavigationStore" />
然后在Login所在的XAML中设置DataContext:
<local:Login> <local:Login.DataContext> <local:LoginViewModel NavigationStore="{StaticResource NavigationStore}" /> </local:Login.DataContext> </local:Login>
3. 增加调用时机防护
确保GrantAccess方法是在Login控件构造完成后才被调用。可以在方法开头加空判断做兜底:
private void GrantAccess() { if (_loginViewModel == null) { MessageBox.Show("ViewModel未完成初始化"); return; } // 原有业务逻辑... }
为什么不能手动new LoginViewModel?
你尝试的LoginViewModel loginViewModel = new LoginViewModel();会报错,是因为构造函数必须传入NavigationStore参数。更关键的是,手动new会创建全新的LoginViewModel实例,它的NavigationStore和全局导航使用的不是同一个,会导致导航状态混乱,因此必须复用全局的NavigationStore来创建LoginViewModel。
内容的提问来源于stack exchange,提问作者Dark Apogee

