Не удается найти пространство имен GalaSoft.MvvmLight.CommandWpf в MVVM Light 5.2.0.37222

Я только что попытался обновить один из моих проектов WPF с MVVM Light 4.2.30 до 5.2. После этого я заметил, что мои RelayCommands больше не запускают свои CanExecute методы.

После быстрого поиска я нашел несколько статей, объясняющих проблему и предлагающих использовать пространство имен GalaSoft.MvvmLight.CommandWpf вместо GalaSoft.MvvmLight.Command. Однако я не могу найти пространство имен GalaSoft.MvvmLight.CommandWpf. Когда я смотрю на GalaSoft.MvvMGalaSoft.MvvmLight.dll в «Обозревателе объектов» Visual Studio, я также не могу найти это пространство имен.

Как кажется, ни у кого другого, кроме меня, есть такая проблема - есть идеи, что я делаю неправильно?

Обновление:

Я создал небольшой пример проекта, который показывает, как я сейчас использую RelayCommands с их методами CanExecute в версии 4.2.30 MVVM light:

public class ViewModel : ViewModelBase
{
    private bool _isReadOnly = false;

    public ViewModel ()
    {
        this.DoSomethingCommand = new RelayCommand(DoSomething, CanDoSomething);
    }

    public bool IsReadOnly
    {
        get
        {
            return _isReadOnly;
        }

        set
        {
            _isReadOnly = value;
            this.RaisePropertyChanged("IsReadOnly");

            // With MVVMLight 4.2.30.23246 I did not need to call the RaiseCanExecuteChanged on any of my RelayCommands
            // DoSomethingCommand.RaiseCanExecuteChanged(); 
        }
    }

    public RelayCommand DoSomethingCommand { get; set; }

    private bool  CanDoSomething()
    {
        return !this.IsReadOnly;
    }

    private void DoSomething()
    {
        MessageBox.Show("Let's break the MVVM idea...");
    }
}

Код XAML представления:

<Window x:Class="MVVMLight5.2CanExecuteTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:MVVMLight5._2CanExecuteTest"
    mc:Ignorable="d"
    Title="Test" Height="150" Width="200">
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <CheckBox HorizontalAlignment="Center" Grid.Row="0" Grid.Column="0" Content="Is read only" IsChecked="{Binding IsReadOnly, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
    <Button Grid.Row="1" Grid.Column="0" Content="Break me" Command="{Binding DoSomethingCommand}"/>
</Grid>

My target is that if I have a button in the View that uses the 'DoSomethingCommand' as a Command then this button should become disabled when my IsReadOnly property is turned to false. When using MVVM light 4.2.30 then this works without any additional so far but in MVVM light 5.2 I need to add the DoSomethingCommand.RaiseCanExecuteChanged(); to make the button go disabled in view.

Могу ли я как-то получить старое поведение с новой легкой структурой MVVM?


person Ralf    schedule 10.11.2015    source источник
comment
Класс RelayCommand находится в пространстве имен CommandWpf, только если вы ссылаетесь на PCL (переносимую) версию библиотеки. При нацеливании на .NET 4.0 и ниже он находится в пространстве имен Command. Вы уверены, что виноват MvvmLight? Можете ли вы опубликовать любой код?   -  person Patrick Quirk    schedule 10.11.2015
comment
Нет, я не использую портативную версию — я имею в виду обычную версию библиотеки 4.5. Почему это доступно только в версии PCL и только для .NET 4.0? Как мне тогда решить мою проблему?   -  person Ralf    schedule 10.11.2015
comment
Пока ответа не нашел. А пока мне интересно, как должны вызываться методы CanExecute в текущих версиях MVVM light: Вручную? Может через таймер?   -  person Ralf    schedule 16.11.2015
comment
Можете ли вы опубликовать код, который вы используете для привязки к команде, а также код для создания команды и самого метода CanExecute? У меня нет никаких проблем с этим, и я не знаю о каких-либо текущих ошибках, когда CanExecute не вызывается. Либо так, либо создайте SSCCE, в котором обнаружена ошибка.   -  person Patrick Quirk    schedule 16.11.2015
comment
Привет Патрик! Извините за более поздний ответ.... Я обновил свой пост.   -  person Ralf    schedule 18.11.2015


Ответы (1)


TL;DR: убедитесь, что у вас есть ссылка на GalaSoft.MvvmLight.Platform, после чего вы сможете использовать пространство имен CommandWpf. Или дважды проверьте, что вы связываетесь с версией .NET 4.5 MVVM Light; Я думаю, вы ссылаетесь на версию .NET 4.0.

Лоран (автор MVVMLight) на самом деле имеет v5/" rel="nofollow noreferrer">рассказал обо всем этом в своем блоге. О том, почему он создал другое пространство имен:

В переносимой версии библиотеки классов MVVM Light отсутствует CommandManager.

...

Первым очевидным решением, которое я рассматривал, было следующее: переместить RelayCommand из сборки GalaSoft.MvvmLight.dll в GalaSoft.MvvmLight.Platform.dll. Поскольку эта DLL не является PCL (отсюда и название «платформа»), она может содержать элементы, зависящие от платформы. Если я перемещу туда RelayCommand, он будет работать с CommandManager, как и раньше. Однако он больше не будет доступен для сборок на основе PCL, что является реальной проблемой. Вот почему я отказался от этого решения.

Вместо этого я решил продублировать класс RelayCommand. Если вы проверите исходный код WPF, вы увидите, что этот класс связан в сборке GalaSoft.MvvmLight, а также в сборке GalaSoft.MvvmLight.Platform. Это же класс! Однако во избежание конфликтов сборка Platform объявляется в пространстве имен GalaSoft.MvvmLight.CommandWpf.

В этом контексте я все еще немного смущен тем, почему все так, как есть. Когда я разбираю библиотеки, опубликованные на Nuget, вот что я вижу:

MvvmLightLibs.5.2.0.0\lib\net40 (версия сборки 5.2.0.37222):

namespace GalaSoft.MvvmLight.Command
{
    /// <omitted, see below>
    public class RelayCommand<T> : ICommand
    {
        private readonly WeakAction<T> _execute;
        private readonly WeakFunc<T, bool> _canExecute;

        /// <summary>
        /// Occurs when changes occur that affect whether the command should execute.
        /// 
        /// </summary>
        public event EventHandler CanExecuteChanged;

MvvmLightLibs.5.2.0.0\lib\net45 (версия сборки 5.2.0.37223):

namespace GalaSoft.MvvmLight.Command
{
    /// <omitted, see below>
    public class RelayCommand<T> : ICommand
    {
        private readonly WeakAction<T> _execute;
        private readonly WeakFunc<T, bool> _canExecute;

        /// <summary>
        /// Occurs when changes occur that affect whether the command should execute.
        /// 
        /// </summary>
        public event EventHandler CanExecuteChanged
        {
            add
            {
                if (this._canExecute == null)
                    return;
                CommandManager.RequerySuggested += value;
            }
            remove
            {
                if (this._canExecute == null)
                    return;
                CommandManager.RequerySuggested -= value;
            }
        }

Обратите внимание, что версия 4.5 CanExecuteChanged использует CommandManager класс, поэтому вам никогда не нужно было вызывать RaiseCanExecuteChanged(). Версия 4.0 — это обычное событие, поэтому вам нужно позвонить RaiseCanExecuteChanged() самостоятельно.

Также обратите внимание, что версии сборки различаются между ними, и, поскольку в своем вопросе вы говорите, что используете 5.2.0.37222, я бы сказал, что вы используете библиотеку 4.0. Вот почему я думаю, что просто ссылка на версию 4.5 исправит это.

К сожалению, я не могу понять, почему эти две версии отличаются, глядя на исходный код. Ни одна из этих трех констант не определена в версия проекта .NET 4.0, так почему же он не создает ветку с CommandManager?

person Patrick Quirk    schedule 18.11.2015
comment
Добавление GalaSoft.MvvmLight.Platform.dll в качестве ссылки позволило мне использовать пространство имен GalaSoft.MvvmLight.CommandWpf и таким образом решило мою проблему. Я должен признать, что я, должно быть, был каким-то глупым, чтобы не понять этого с самого начала (я также прочитал сообщение Лорана), прежде чем начать эту тему здесь. Спасибо за помощь и извините за беспокойство... :-/ - person Ralf; 20.11.2015
comment
Чем глубже я заходил, тем больше запутывался, так что это вполне понятно! - person Patrick Quirk; 20.11.2015