简体   繁体   English

将Mvvm Light更新为版本5后,我需要做哪些更改才能使RelayCommand CanExecute()工作?

[英]After updating Mvvm Light to Version 5, what changes do I need to make RelayCommand CanExecute() work?

I updated Mvvm Light to version 5 and noticed that RelayCommand stopped working. 我将Mvvm Light更新为版本5并注意到RelayCommand停止工作。

The problem seems to be that the CanExecute() is not being called to validate. 问题似乎是没有调用CanExecute()进行验证。 It only validates one time, like when the window is loaded. 它只验证一次,就像加载窗口时一样。

Could this be a bug from the recent update or is there something I need to change in the XAML? 这可能是最近更新中的错误还是我需要在XAML中更改某些内容?

Everything was working correctly before the update. 在更新之前一切正常。 I'm working with WPF. 我正在使用WPF。

See this MVVM Light 5 issue : 看到这个MVVM Light 5问题

WPF is the only XAML framework that uses the CommandManager to automagically raise the CanExecuteChanged event on ICommands. WPF是唯一一个使用CommandManager在ICommands上自动引发CanExecuteChanged事件的XAML框架。 I never liked that approach, because of the "magic" part, but this is a "feature" of WPF and of course I have to support it. 我从不喜欢这种方法,因为“神奇”部分,但这是WPF的“功能”,当然我必须支持它。 No question here. 这里没问题。

In V5, I moved to portable class library for all the newest versions of the XAML frameworks, including WPF4.5. 在V5中,我转移到了所有最新版本的XAML框架的可移植类库,包括WPF4.5。 Unfortunately, there is no CommandManager in PCL, and I have to admit that I didn't realize that at first sight. 不幸的是,PCL中没有CommandManager,我不得不承认我没有意识到这一点。 So of course now the automagical part doesn't work anymore. 所以当然现在自动部件不再起作用了。 Again, so sorry about that. 再一次,很抱歉。

I am not expecting you to raise CanExecuteChanged everywhere now , not after using the CommandManager in your application, which is what the WPF team intended. 我不希望你现在到处都提出CanExecuteChanged ,而不是在你的应用程序中使用CommandManager之后,这是WPF团队的意图。 So I will try to find a way to restore the CommandManager usage in the WPF4.5 version of the toolkit. 因此,我将尝试在WPF4.5版本的工具包中找到恢复CommandManager用法的方法。

Definitely not looking for excuses ;) but hope that explaining why the issue arose helps to make sense of this. 绝对不寻找借口;)但希望解释为什么问题出现有助于理解这一点。 It's going to be my priority No. 1 until I find a way to solve this in the PCL version. 在我找到一种方法在PCL版本中解决这个问题之前,这将是我的第一号优先事项。 In the meantime, like I mentioned before, I think that going back to V4.4.32.7 should fix that. 与此同时,正如我之前提到的,我认为回到V4.4.32.7应该可以解决这个问题。 Please let me know if it does not. 如果没有,请告诉我。

So the temporary recommended solution is to revert back to the previous version . 因此,临时建议的解决方案是恢复到以前的版本 I did it and it worked. 我做到了它并且有效。

I agree that the CommandManager is doing "magic". 我同意CommandManager正在做“魔术”。 Once I had null reference exception within the CanExecute condition and as a result I have obtained neverending cycle of error messages like cards in Windows Solitaire. 一旦我在CanExecute条件中CanExecute引用异常,结果我已经获得了像Windows Solitaire中的卡一样的错误消息的CanExecute循环。 If I started a new project I would prefer not to use this "magic" but to change an existing and already deployed project would be quite painful. 如果我开始一个新项目,我宁愿不使用这个“魔术”,但改变现有的已经部署的项目将是非常痛苦的。

Looks like you have to call RaiseCanExecuteChanged on the command whenever a relevant property is changed. 看起来每当相关属性发生变化时,您必须在命令上调用RaiseCanExecuteChanged。 I think this was previously done by the wpf command manager, but the recent PCL changes probably made that unsupportable. 我认为这是以前由wpf命令管理器完成的,但最近的PCL更改可能使得它不受支持。

I use MvvmCross which requires a similar method to be called, so in my base view model I have a method allowing me to register a command so that whenever a property changed occurs I can loop all registered commands and force canexecute to be called again. 我使用MvvmCross,它需要一个类似的方法来调用,所以在我的基本视图模型中,我有一个允许我注册命令的方法,这样每当属性发生变化时,我都可以循环所有已注册的命令并强制再次调用canexecute。 To make things easier you could do it that way. 为了方便起见,你可以这样做。

Check out this sample 看看这个样本

As this seems to be doubted, here is some code I have tested 由于这似乎有所怀疑,这里有一些我测试过的代码

using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using System;

namespace TestingApp.ViewModel
{
    /// <summary>
    /// This class contains properties that the main View can data bind to.
    /// <para>
    /// Use the <strong>mvvminpc</strong> snippet to add bindable properties to this ViewModel.
    /// </para>
    /// <para>
    /// You can also use Blend to data bind with the tool's support.
    /// </para>
    /// <para>
    /// See http://www.galasoft.ch/mvvm
    /// </para>
    /// </summary>
    public class MainViewModel : ViewModelBase
    {
        private Int32 _increment = 0;

        public Int32 Increment
        {
            get { return _increment; }
            set
            {
                _increment = value;
                RaisePropertyChanged("Increment");
                GoCommand.RaiseCanExecuteChanged();
            }
        }

        /// <summary>
        /// Initializes a new instance of the MainViewModel class.
        /// </summary>
        public MainViewModel()
        {
            ////if (IsInDesignMode)
            ////{
            ////    // Code runs in Blend --> create design time data.
            ////}
            ////else
            ////{
            ////    // Code runs "for real"
            ////}
        }

        private RelayCommand _incrementCommand;

        public RelayCommand IncrementCommand
        {
            get
            {
                if (_incrementCommand == null)
                {
                    _incrementCommand = new RelayCommand(IncrementCommand_Execute);
                }
                return _incrementCommand;
            }
        }

        private void IncrementCommand_Execute()
        {
            Increment++;
        }

        private RelayCommand _goCommand;

        public RelayCommand GoCommand
        {
            get
            {
                if (_goCommand == null)
                {
                    _goCommand = new RelayCommand(GoCommand_Execute, GoCommand_CanExecute);
                }
                return _goCommand;
            }
        }

        private bool GoCommand_CanExecute()
        {
            return Increment > 5;
        }

        private void GoCommand_Execute()
        {
            //
        }
    }
}

Without the line 没有线

GoCommand.RaiseCanExecuteChanged();

the canexecute method is never called after the initial call, but with the line it is called everytime the Increment property changes 在初始调用之后永远不会调用canexecute方法,但是每次Increment属性更改时都会调用它

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM