Параметры ICommand всегда нулевые - PullRequest
2 голосов
/ 26 января 2012

Я пытаюсь извлечь часть своего пользовательского интерфейса (текст из текстовых полей) в качестве параметров в метод ICommand, расположенный в моей модели представления.

Прежде всего, я получил эту реализацию RelayCommand:

/// <summary>
/// A command whose sole purpose is to relay its functionality to other
/// objects by invoking delegates. The default return value for the
/// CanExecute method is 'true'.
/// </summary>
public class RelayCommand : ICommand
{
    #region Fields

    readonly Action<object> _execute;
    readonly Predicate<object> _canExecute;

    #endregion // Fields

    #region Constructors

    /// <summary>
    /// Creates a new command that can always execute.
    /// </summary>
    /// <param name="execute">The execution logic.</param>
    public RelayCommand(Action<object> execute)
        : this(execute, null)
    {
    }

    /// <summary>
    /// Creates a new command.
    /// </summary>
    /// <param name="execute">The execution logic.</param>
    /// <param name="canExecute">The execution status logic.</param>
    public RelayCommand(Action<object> execute, Predicate<object> canExecute)
    {
        if (execute == null)
            throw new ArgumentNullException("execute");

        _execute = execute;
        _canExecute = canExecute;
    }

    #endregion // Constructors

    #region ICommand Members

    [DebuggerStepThrough]
    public bool CanExecute(object parameters)
    {
        return _canExecute == null ? true : _canExecute(parameters);
    }

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    public void Execute(object parameters)
    {
        _execute(parameters);
    }

    #endregion // ICommand Members
}

Я объявил команду в моей модели представления следующим образом:

public ICommand AddEntityCommand
{
    get
    {
        if(_addEntity == null)
        {
            _addEntity = new RelayCommand(AddEntityToDb);
        }

        return _addEntity;
    }
}

Это мое определение xaml:

<Label Content="Entity Name:" Name="label1"/>
<TextBox Name="textBox_EntityName" />
<Label Content="Entity Type:" Name="label2" />
<TextBox Name="textBox_EntityType" />
<Button Content="Add" Name="btnAdd" Command="{Binding Path=AddEntityCommand}">
    <Button.CommandParameter>
        <MultiBinding Converter="{StaticResource MultiParamConverter}">
            <Binding Path="Text" ElementName="textBox_EntityName" />
            <Binding Path="Text" ElementName="textBox_EntityType" />
        </MultiBinding>
    </Button.CommandParameter>
</Button>

и, наконец, это мой конвертер:

public class MultiParamConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return (object)values;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Я отлаживал инструмент несколько раз, и отладчик останавливался в конвертере, как только я изменял значение в текстовом поле.В этом случае значения из пользовательского интерфейса отображаются в параметре

object[] values

.Нажав кнопку, я не позволю мне остановиться в конвертировании, но он правильно вызывает метод

AddEntityToDb

, но параметр, который имеет тип объекта [], всегда содержит два элемента, оба из которых равны нулю.

Я думаю, что сделал что-то ужасно неправильное при создании команды AddEntityCommand, но я не могу понять это самостоятельно.Но какова причина того, что параметр AddEntityToDb всегда содержит два нулевых элемента?

Ответы [ 2 ]

3 голосов
/ 26 января 2012

Я не знаю, почему он не работает должным образом, но в любом случае вам не нужно использовать параметры команды ... Вы можете привязать текстовые поля к свойствам вашей модели представления и использовать значения этих свойств в вашем AddEntityToDb методе. Это самый распространенный способ сделать это в MVVM ...


РЕДАКТИРОВАТЬ: Я воспроизвел вашу первоначальную проблему с конвертером. Я думаю, причина в том, что MultiBinding очищает массив values после вызова Convert (возможно, чтобы избежать утечек памяти). Исправление заключается в клонировании массива вместо прямого возврата:

using System.Linq;

...


public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
    return values.ToArray();
}
0 голосов
/ 26 января 2012

ОБНОВЛЕНИЕ: попробуйте это

public class MultiParamConverter : IMultiValueConverter
{
   public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
   {
      return new Tuple<string, string>((string)values[0], (string)values[1]);;
   }

public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
    throw new NotImplementedException();
}
}

viewmodel

public void AddEntityToDb(object parameter)
{
    var values = (Tuple<string, string>)parameter;
    var text1 = values.Item1;
    var text2 = values.Item2;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...