WPF和RelayCommand - 按钮总是触发

Bri*_*nKE 0 wpf button

我一直在努力通过一些MVVM和WPF的例子,同时做一些调试我发现,一个按钮上我认为相关的RelayCommand不断射击(执行相关ImportHoursCommand)一旦程序启动.

以下是代码段:

视图

<Button x:Name="ImportHoursButton" Content="Import Hours" 
        Command="{Binding ImportHoursCommand}" 
        Height="25" Width="100" Margin="10"
        VerticalAlignment="Bottom" HorizontalAlignment="Right"                
        Grid.Row="1" />
Run Code Online (Sandbox Code Playgroud)

视图模型

        private RelayCommand _importHoursCommand;
        public ICommand ImportHoursCommand
        {
            get
            {
                if (_importHoursCommand == null)
                {
                    _importHoursCommand = new RelayCommand(param => this.ImportHoursCommandExecute(), 
                                                            param => this.ImportHoursCommandCanExecute);
                }
                return _importHoursCommand;
            }
        }

        void ImportHoursCommandExecute()
        {
            MessageBox.Show("Import Hours",
                            "Hours have been imported!",
                            MessageBoxButton.OK);
        }

        bool ImportHoursCommandCanExecute
        {
            get
            {
                string userProfile = System.Environment.GetEnvironmentVariable("USERPROFILE");
                string currentFile = @userProfile + "\\download\\test.txt";
                if (!File.Exists(currentFile))
                {
                    MessageBox.Show("File Not Found", 
                                    "The file " + currentFile + " was not found!", 
                                    MessageBoxButton.OK);
                    return false;
                }
                return true;
            }
        }
Run Code Online (Sandbox Code Playgroud)

如果我在'string userProfile = ...'行放置断点并运行程序,Visual Studio将在断点处停止并在每次单击调试"继续"按钮时继续在断点处停止.如果我没有断点,程序似乎运行正常,但该命令是否始终检查它是否可以执行?

我使用的约什-史密斯的文章RelayCommand 这里.

Rac*_*hel 6

如果将Button绑定到Command,则CanExecute()确定是否启用了Button.这意味着CanExecute()只要按钮需要检查其启用值,例如在屏幕上绘制时,就会运行.

由于你在VS中使用断点,我猜测当VS获得焦点时应用程序被隐藏,并且当你点击"继续"按钮时它正在重新绘制按钮.当它重新绘制按钮时,它会CanExecute()再次进行评估,进入您所看到的无限循环

确切知道的一种方法是将断点更改为a Debug.WriteLine,并在应用程序运行时观察输出窗口.

作为旁注,您还可以将您更改RelayCommand为Microsoft Prism DelegateCommand.我没有太仔细地看待这些差异,但是我知道在满足某些条件(属性更改,视觉无效等)时会RelayCommands自动引发CanExecuteChanged()事件,而DelegateCommands只有在您明确告知时才会引发此事件.这意味着CanExecute()只会根据您的具体情况评估您何时明确告知,而不是自动判断哪种情况好坏.