gpt4 book ai didi

c# - WPF MVVM Light : Command. RaiseCanExecuteChanged() 不起作用

转载 作者:太空宇宙 更新时间:2023-11-03 20:13:28 26 4
gpt4 key购买 nike

我的 ViewModel 中有这样的东西:

public enum WorkState
{
Idle, Working, Stopping
};

public class MainViewModel : ViewModelBase
{
public const string StatePropertyName = "State";
private WorkState _state = WorkState.Idle;
public WorkState State
{
get
{ return _state; }
set
{
if (_state == value)
{
return;
}

RaisePropertyChanging(StatePropertyName);
_state = value;
RaisePropertyChanged(StatePropertyName);

StartStopCommand.RaiseCanExecuteChanged(); // <—————————————
}
}


private RelayCommand _startStopCommand;
public RelayCommand StartStopCommand
{
get
{
return _startStopCommand
?? (_startStopCommand = new RelayCommand(
() =>
{
if (State == WorkState.Idle)
{
State = WorkState.Working;
}
else if (State == WorkState.Working)
{
State = WorkState.Stopping;

new Thread(() =>
{
Thread.Sleep(5000);
State = WorkState.Idle;
}).Start();
}
},
() => (State == WorkState.Idle ||
(State == WorkState.Working)));
}
}
}

还有我 View 中的按钮:

        <Button Command="{Binding StartStopCommand}">
<Button.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding State}" Value="{x:Static vm:WorkState.Idle}">
<Setter Property="Button.Content" Value="Start"/>
</DataTrigger>
<DataTrigger Binding="{Binding State}" Value="{x:Static vm:WorkState.Working}">
<Setter Property="Button.Content" Value="Stop"/>
</DataTrigger>
<DataTrigger Binding="{Binding State}" Value="{x:Static vm:WorkState.Stopping}">
<Setter Property="Button.Content" Value="Stop"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>

但是当我按下 Stop 按钮并且 State 属性更改为 Idle 时,按钮仅将其文本更改为“Start”但在我单击窗口中的某个位置之前保持禁用状态。

我将 RaiseCanExecuteChanged 添加到 State 属性的 setter 中,但没有帮助。

我做错了什么?

此外,我不确定这种在同一命令中使用启动/停止和设置按钮文本的 DataTriggers 的方法是最好的,所以如果有人分享更好的方法,我将不胜感激。

最佳答案

这里的问题不是 RaiseCanExecuteChanged() 不工作,而是当您的 UI 依赖它时从后台线程修改您的 State 属性。

假设我将您的代码相应地修改为:(这是与 .Net 4.5 一起使用的)

public RelayCommand StartStopCommand { get; set; }

...

public MainViewModel() {
StartStopCommand = new RelayCommand(async () => {
switch (State) {
case WorkState.Idle:
State = WorkState.Working;
break;
case WorkState.Working:
State = WorkState.Stopping;
await Task.Delay(5000);
State = WorkState.Idle;
break;
}
}, () => State == WorkState.Idle || State == WorkState.Working);
}

现在您可以看到 Button 从禁用状态正确切换回启用状态。

您可以从以下网址获取示例:Here

如果你想坚持使用你的Thread,将它切换到:

new Thread(
() => {
Thread.Sleep(5000);
Application.Current.Dispatcher.BeginInvoke(
new Action(() => State = WorkState.Idle));
}).Start();

^^ 这现在又可以正常工作了,因为您没有从另一个线程修改属性。

关于c# - WPF MVVM Light : Command. RaiseCanExecuteChanged() 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18385213/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com