如果使用了局部变量,RelayCommand Execute delegate不起作用

本文关键字:RelayCommand Execute delegate 不起作用 局部变量 如果 | 更新日期: 2023-09-27 17:50:41

我试图在方法中创建MVVM Light RelayCommand:

protected RelayCommand NavigateToViewCommand(string viewName) {
#if false
    return new RelayCommand(() => {
        Debug.WriteLine("It fired.");
        Navigation.Navigate(ServiceLocator.Current.GetInstance<IViewLocator>().GetViewForNavigation("StudentPage2"));
    });
#else
    return new RelayCommand(() => {
        Debug.WriteLine("It fired.");
        Navigation.Navigate(ServiceLocator.Current.GetInstance<IViewLocator>().GetViewForNavigation(viewName));
    });
#endif
}

如果我在RelayCommand的Execute委托中使用viewName参数的方法,它将不会触发。我将这个命令绑定到一个按钮。当我单击该按钮时,甚至Debug.WriteLine命令也不会触发(并且放置在其上的断点不会中断)。

但是,如果我用与viewName中的值相同的硬编码字符串替换viewName参数,则RelayCommand工作正常。

请注意,下面的代码没有在按钮中使用命令,执行时不会出现问题:

void Test() {
    Command1.Execute(null);
    Command2("David").Execute(null);
}
RelayCommand Command1 { get { return new RelayCommand(() => Debug.WriteLine("cmd1 executed.")); } }
RelayCommand Command2(string msg) { return new RelayCommand(() => Debug.WriteLine("cmd2 executed: " + msg)); }

但是如果我在Xaml中绑定Command2Button.Command,它不会执行:

public ICommand TestCommand2 { get { return Command2("Cater"); } }
<Button Grid.Row="1" Grid.Column="1" Command="{Binding TestCommand2}" Content="TEST" />

你知道这是怎么回事吗?

进一步的实验表明,在Execute委托中使用虚拟属性而不是参数似乎确实有效。在此代码中由NavigateToViewCommand创建的命令在绑定到button.Command时运行良好。当然,这并不能解决问题;这只是更多的信息。

// In base class:
protected RelayCommand NavigateToViewCommand() {
    return new RelayCommand(() => Navigation.Navigate(ServiceLocator.Current.GetInstance<IViewLocator>().GetViewForNavigation(NextPageViewName)));
}
protected virtual string NextPageViewName { get { return string.Empty; } }
// In subclass:
private ICommand m_nextPage;
public ICommand NextPageCommand { get { return m_nextPage ?? (m_nextPage = NavigateToViewCommand()); } }
protected override string NextPageViewName { get { return "StudentPage2"; } }

如果使用了局部变量,RelayCommand Execute delegate不起作用

我倾向于使用内置的 ICommand模式,而不是将此参数传递给RelayCommand ctor,这意味着:

protected RelayCommand NavigateToViewCommand() 
{
    return new RelayCommand((viewName) => {
        Debug.WriteLine("It fired.");
        Navigation.Navigate(ServiceLocator.Current
                  .GetInstance<IViewLocator>()
                  .GetViewForNavigation(viewName.ToString()));
    });
}

和调用execute:

NavigateToViewCommand().Execute("David");

这是向命令传递参数的一种更温和的方式。附注:我没有试过这个。