WPF& RelayCommand - 按钮始终触发

时间:2011-12-08 15:11:44

标签: wpf button

我一直在研究MVVM和MV的一些例子。 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" />

视图模型

        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;
            }
        }

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

我正在使用Josh Smith的文章here中的RelayCommand。

2 个答案:

答案 0 :(得分:6)

如果Button与命令绑定,CanExecute()将确定是否启用了Button。这意味着只要按钮需要检查它的启用值,就会运行CanExecute(),例如当它在屏幕上绘制时。

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

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

作为旁注,您还可以将RelayCommand更改为Microsoft Prism DelegateCommand。我没有仔细查看差异,但是我知道RelayCommands会在满足某些条件(属性更改,视觉无效等)时自动引发CanExecuteChanged()事件,而DelegateCommands只会CanExecute()当你明确告诉它时,举起这个事件。这意味着{{1}}仅在您明确告知时,而不是根据您的情况自动判断哪些可能是好的。

答案 1 :(得分:2)

这是完全正常的; WPF重新评估命令是否可以经常执行,例如,当焦点控件更改时,或窗口获得焦点时。每次单击“继续”时,窗口将再次获得焦点,重新评估命令的CanExecute,以便再次点击断点。