Привязка Viewmodel к CommandParameter, который использует конвертер в WPF - PullRequest
0 голосов
/ 31 января 2020

Я пытаюсь привязать число к Enum, расположенному в модели представления. Я не смог передать значение из представления в модель представления через конвертер. Это вообще возможно? Я не видел в Интернете ничего, что решало бы это, и ни одна из моих попыток не сработала.

Viewmodel

public enum TimerOptions
{
    FifteenMinutes,
    OneHour, 
    Tomorrow
}

private ICommand _timerCommand;
public ICommand TimerCommand => _timerCommand ?? 
                           (_timerCommand = new RelayCommand<TimerOptions>(StartTimer));

private async void StartTimer(TimerOptions option){ .... }

Просмотр

<Button Command="{Binding TimerCommand}" 
        Tag="0" 
        CommandParameter="{Binding Path=Tag, Converter={StaticResource BidirectionalEnumConverter}}">15 minutes</Button>

В приведенном выше примере, когда пользователь нажимает кнопку, Я хочу, чтобы моя функция получила первое значение перечисления FifteenMinutes в качестве параметра. Я попробовал это, добавив Tag (как видно), добавив x:Name к кнопке, а также поиграв с Source и Path в привязке. Ничего не сработало.

Возможно ли это? Я пытался решить эту проблему часами, я ничего не нашел в Интернете.

1 Ответ

0 голосов
/ 01 февраля 2020

Я хочу, чтобы моя функция получила первое значение перечисления FifteenMinutes в качестве параметра.

Почему бы просто не выполнить операцию преобразователя в виртуальной машине из информации, переданной в строке в параметр команды?

Пример

<Button Command="{Binding TimerCommand}" 
        Tag="1" 
        CommandParameter=1

Затем создайте ICommand на основе этого, например

public ICommand TimerCommand =>
        new OperationCommand(async (oTag) => await StartTime(oTag).ConfigureAwait(true));

private bool IsOperation { get; set; }

private async void StartTimer(object oTag)
{
    int tagId = (int)oTag;
    //.... do the convert operations here...
      ...
   // Access VM properties here
   IsOperation = true;

    await  ....;

}


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

public class OperationCommand : ICommand
{

    #region Variables

    private Func<object, bool> CanExecuteHandler { get; set; }
    private Action<object> ExecuteActionHandler { get; set; }

    public bool InSeparateThread { get; set; }
    #endregion

    #region Properties

    #endregion

    #region Construction/Initialization

    public OperationCommand(Action<object> executeAction, bool inSeparateThread = false)
    {
        InSeparateThread = inSeparateThread;
        ExecuteActionHandler = executeAction 
                                   ?? throw new ArgumentNullException(nameof(executeAction));
    }

    public OperationCommand(Action<object> executeAction, 
                            Func<object, bool> canExecute) : this(executeAction)
    {
        CanExecuteHandler = canExecute;
    }

    // Here to adhere to ICommand, change to below if needed
    //public event EventHandler CanExecuteChanged;
    event EventHandler ICommand.CanExecuteChanged
    {
        add {}
        remove {}
    }

    #endregion

    #region Methods

    public bool CanExecute(object parameter) => CanExecuteHandler?.Invoke(parameter) ?? true;

//        public void RaiseCanExecuteChanged() => CanExecuteChanged?.Invoke(this, new EventArgs());

    public void Execute(object parameter)
    {
        ExecuteActionHandler?.Invoke(parameter);
    }

    #endregion
}
}
...