我一直在研究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。
答案 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
,以便再次点击断点。