2015-11-10 16 views
2

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

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

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

Update:

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

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

The 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> 

Моя цель заключается в том, что если у меня есть кнопка в представлении, которая использует команду «DoSomethingCommand» в качестве команды, тогда эта кнопка должна быть отключена, когда свойство IsReadOnly будет повернуто на false. При использовании MVVM light 4.2.30 это работает без каких-либо дополнительных до сих пор, но в свете MVVM 5.2 мне нужно добавить DoSomethingCommand.RaiseCanExecuteChanged(); чтобы кнопка была отключена.

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

+0

Класс 'RelayCommand' находится в пространстве имен' CommandWpf ', только если вы ссылаетесь на PCL (переносную) версию библиотеки. При таргетинге на .NET 4.0 и ниже он находится в пространстве имен 'Command'. Вы уверены, что MvvmLight виноват? Можете ли вы опубликовать любой код? –

+0

Нет Я не использую переносимую версию - я ссылаюсь на обычную версию версии 4.5. Почему это доступно только в версии PCL и только для .NET 4.0? Как я могу исправить свою проблему? – Ralf

+0

На данный момент ответа не найдено. Тем временем мне интересно, как методы CanExecute предназначены для вызова в текущих версиях освещения MVVM: вручную? Может быть, в таймер? – Ralf

ответ

3

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

Лоран (автор MVVMLight) имеет фактически addressed all of this on his blog. Почему он создал другое пространство имен:

В портативной библиотеке классов 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; 
      } 
     } 

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

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

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

+0

Добавление GalaSoft.MvvmLight.Platform.dll в качестве ссылки позволило мне использовать пространство имен GalaSoft.MvvmLight.CommandWpf и, таким образом, решить мою проблему. Я должен признать, что я, должно быть, был каким-то глупым, чтобы не понимать этого с самого начала (я также читал сообщение Лорана), прежде чем начинать эту тему здесь. Спасибо за помощь и извините за неприятности ...: -/ – Ralf

+0

Я только более смутился, чем глубже я пошел, так что это вполне понятно! –