WPF MVVM光:Command.RaiseCanExecuteChanged()不工作 [英] WPF MVVM Light: Command.RaiseCanExecuteChanged() doesn't work

查看:1753
本文介绍了WPF MVVM光:Command.RaiseCanExecuteChanged()不工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在我的视图模型是这样的:

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

现在你可以看到按钮从禁用回到正确的交换机

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆