Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# ICommand是否可以在属性更改后执行不触发?_C#_Wpf_Mvvm Light - Fatal编程技术网

C# ICommand是否可以在属性更改后执行不触发?

C# ICommand是否可以在属性更改后执行不触发?,c#,wpf,mvvm-light,C#,Wpf,Mvvm Light,我得到了一个WPF应用程序,它显示了一个绑定到如下命令的按钮: <Button Command="{Binding Path=TestrunStartCommand}" Content="GO!"> public ICommand TestrunStartCommand { get { return new RelayCommand(TestrunStartExecute, () => !IsTestrunInProgress); } } public bool I

我得到了一个WPF应用程序,它显示了一个绑定到如下命令的按钮:

<Button Command="{Binding Path=TestrunStartCommand}" Content="GO!">
public ICommand TestrunStartCommand
{
    get { return new RelayCommand(TestrunStartExecute, () => !IsTestrunInProgress); }
}

public bool IsTestrunInProgress
{
    get{
        return _isTestrunInProgress;
    }
    set{
        _isTestrunInProgress = value;
        RaisePropertyChanged(IsTestrunInProgressPropertyName);
    }
}   
问题是,在我将
IsTestrunInProgress
设置为false后,该按钮不会立即启用,而只能在我在应用程序窗口内单击后启用

你能帮我理解这种行为,并告诉我如何解决这个问题吗

进一步阅读:

接口
ICommand
会公开一个事件,用于通知UI何时重新确定命令驱动UI组件的
IsEnabled
状态

根据您正在使用的
RelayCommand
的实现情况,您可能需要引发此事件;许多实现公开了一种方法,例如
RelayCommand.raiseCanceTechChanged()
,您可以调用该方法来强制UI刷新

RelayCommand
的一些实现利用了,在这种情况下,您需要调用以强制UI刷新

长话短说,您将需要从属性设置程序调用其中一个方法

更新

当活动焦点改变时,按钮的状态正在确定,我相信正在使用
CommandManager
。因此,在属性的setter中,在分配了backing字段之后,调用

更新2

RelayCommand
实现来自MVVM light toolkit。当从WPF/.NET使用时,实现会包装从
CommandManager
公开的方法和事件。这将意味着这些命令在大多数情况下自动工作(用户界面被改变,或者焦点元素被改变)。但是在一些情况下,例如在本例中,您需要手动强制命令重新查询。使用此库执行此操作的正确方法是调用您可以尝试使用的
RelayCommand
上的
raisecancecutechanged()
方法

不管怎么说,这在过去有时对我没有帮助。对我来说,最好的解决方案是将布尔属性绑定到
按钮

就你的情况来说

IsEnabled={Binding IsTestrunInProgress}

这很重要,很容易错过,我重复@Samir在评论中说的话。Laurent Bugnon先生在他的报告中写道:

然而,在WPF4和WPF4.5中,有一个陷阱:将MVVMLight升级到V5后,CommandManager将停止工作。您将观察到,当RelayCommand的CanExecute委托返回false时,UI元素(按钮等)将停止禁用/启用

如果您赶时间,这里有一个解决方案:在任何使用RelayCommand的类中,替换以下行:

与:


问题是,每当访问ICommand属性TestrunStartCommand时,它总是返回一个新的命令对象

一个简单的修复方法是创建ICommand对象一次,然后反复使用它

private ICommand _testRunCommand = null;
public ICommand TestrunStartCommand
{
    get 
    { 
        return _testRunCommand ?? (_testRunCommand = new RelayCommand(TestrunStartExecute, () => !IsTestrunInProgress)); 
    }
}

这是一个非常简单的修复程序,对我来说很有效。

只有在我在应用程序窗口中单击后才生效;您是否暗示操作系统中当前活动的窗口不是此程序窗口?或者换句话说,此应用程序已启动并正在运行,但您在记事本中,只能在后台看到窗口。@MichaelPerrenoud:不,应用程序窗口处于活动状态并具有焦点。似乎只有在我的窗口内单击时才会计算
CanExecuteChanged
。Galasoft库中的RelayCommand有效effeciently@HichemC我确信它能有效地工作,错误当然在我(初学者)这一边。但是我的错误在哪里?你是对的:我在我的
RelayCommand
中得到了
raisecanextechanged
方法。但我不明白的是,我有很多工作按钮,我从来没有手动启动过这个事件,不知何故,它的工作方式就像魔术一样。在这种情况下有什么不同?我认为这个谜题中仍然缺少一些东西……所有这些按钮都使用了相同的
RelayCommand
?您能告诉我您使用的是哪种实现吗?i、 e.该类来自哪个库?是,所有按钮使用相同的
RelayCommand
。我正在使用。如果使用WPF 4.5或更高版本,则需要使用命名空间GalaSoft.MvvmLight.CommandWpf中的RelayCommand,而不是GalaSoft.MvvmLight.Command。这将重新启用RelayCommand以使用CommandManager。我注意到另一件重要的事情,如果您从非UI线程设置(引起更改的)属性,则需要通过Dispatcher调用上述方法。否则,WPF会吞下通知。是的,像您所说的那样使用绑定,它就像一个符咒一样工作。这首先会破坏使用命令的目的,并且只有在您的启用状态依赖于单个属性时才起作用。非常感谢。。你救了我的周末:)天哪!我在这上面浪费了太多时间,通常我喜欢Mvvm灯,但不是今天。哦,天哪。现在是2020年,距离最初的答案已经5年了,我刚刚花了两个小时的大部分时间试图弄清楚为什么这在一个视图/视图模型中不起作用,但在另一个视图/视图模型中起作用。。。两个命令代码完全相同。。。除了一个使用了
GalaSoft.MvvmLight.Command
而不是
GalaSoft.MvvmLight.CommandWpf
。。。天哪,这太令人沮丧了。
using GalaSoft.MvvmLight.CommandWpf;
private ICommand _testRunCommand = null;
public ICommand TestrunStartCommand
{
    get 
    { 
        return _testRunCommand ?? (_testRunCommand = new RelayCommand(TestrunStartExecute, () => !IsTestrunInProgress)); 
    }
}