WPF MVVM光:Command.RaiseCanExecuteChanged()不工作 [英] WPF MVVM Light: Command.RaiseCanExecuteChanged() doesn't work
问题描述
我在我的视图模型是这样的:
I have something like this in my 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)));
}
}
}
和按钮,在我的观点:
And button in my 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>
但是,当我按下停止按钮和国家属性更改为空闲,按钮仅改变其文本开始,但直到我在窗口中单击某个地方仍处于禁用状态。
But when I press Stop button and the State property changes to Idle, button only changes its' text to "Start" but remains disabled until I click somewhere in the window.
我添加RaiseCanExecuteChanged到国家财产的二传手,但它并没有帮助。
I added RaiseCanExecuteChanged to the setter of the State property but it didn't help.
我在做什么错了?
另外,我不知道这种做法与启动/停止在同一个命令和DataTriggers对于设置按钮文本是最好的,所以如果有人分享更好的办法做到这一点,我将不胜感激。
Also I am not sure that this approach with Start/Stop in the same command and DataTriggers for settings button text is the best so I would be grateful if someone shares better way to do this.
推荐答案
您的问题在这里ISN T RaiseCanExecuteChanged()
没有工作,但是从后台线程修改你的国家
属性时,你的UI依赖于它。
Your problem here isn't RaiseCanExecuteChanged()
not working but modifying your State
property from a background thread when your UI depends on it.
所以说,如果我相应的修改您的代码(这是.NET 4.5)
So say if I modified your code accordingly to: (This is with .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);
}
现在你可以看到按钮$ C 。$ C>从禁用回到正确的交换机
Now you can see the Button
switches from disabled back to enabled correctly.
您可以得到样品:的这里
如果你想坚持你的发
,切换到:
If you want to stick with your Thread
, switch it to:
new Thread(
() => {
Thread.Sleep(5000);
Application.Current.Dispatcher.BeginInvoke(
new Action(() => State = WorkState.Idle));
}).Start();
^^这将现在又工作得很好,因为你不修改从另一个线程的属性。
^^ this would now again work fine since you do not modify the property from another thread.
这篇关于WPF MVVM光:Command.RaiseCanExecuteChanged()不工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!