AvaloniaUI/Avalonia.Xaml.Behaviors

InvokeCommandAction on ReactiveCommand Issue

Tenjim opened this issue · 1 comments

Hi,

I have found an issue while using an InvokeCommandAction on ReactiveCommand :

Command requires parameters of type System.Reactive.Unit, but received parameter of type Avalonia.Controls.SelectionChangedEventArgs_

Example from DragAndDropSample :

<ListBox Items="{Binding Items}"
           Classes="ItemsDragAndDrop">
    <ListBox.ItemTemplate>
      <DataTemplate DataType="vm:ItemViewModel">
        <TextBlock Text="{Binding Title}" />
      </DataTemplate>
    </ListBox.ItemTemplate>
    <Interaction.Behaviors>
      <EventTriggerBehavior EventName="SelectionChanged">
        <InvokeCommandAction Command="{Binding TestCommand}"/>
      </EventTriggerBehavior>
    </Interaction.Behaviors>

  </ListBox>
public class MainWindowViewModel : ViewModelBase
    {
        private ObservableCollection<ItemViewModel> _items;
        
        public ObservableCollection<ItemViewModel> Items
        {
            get => _items;
            set => this.RaiseAndSetIfChanged(ref _items, value);
        }

        public ICommand TestCommand => ReactiveCommand.Create(AddTest);

        public MainWindowViewModel()
        {
            _items = new ObservableCollection<ItemViewModel>()
            {
                new() { Title = "Item0" },
                new() { Title = "Item1" },
                new() { Title = "Item2" },
                new() { Title = "Item3" },
                new() { Title = "Item4" }
            };
        }

        public void AddTest()
        {
            Items.Add(new ItemViewModel { Title = "Test" });
        }
    }

Is it possible to use ReactiveCommand with TriggerBehavior with InvokeCommandAction (It's working wpf projects) ?

Thank in advance.

Hi,

the issue came from InvokeCommandAction.cs.
When we want to execute ReactiveCommand, we have CommandParameter property to null and for this case. It won't execute this command because it expect have an SelectionChangedArgs as parameter.

I try to fix that with checking CommandParameter is null or not and put the resolvedparameter(from InvokeCommandAction.Execute method) to null like this:

 public virtual object Execute(object? sender, object? parameter)
  {
      if (Command is null)
      {
          return false;
      }

      object? resolvedParameter;
      **if (this.CommandParameter == null)
      {
          resolvedParameter = null;
      }**
      else if (IsSet(CommandParameterProperty))
      {
          resolvedParameter = CommandParameter;
      }
      else if (InputConverter is { })
      {
          resolvedParameter = InputConverter.Convert(
              parameter,
              typeof(object),
              InputConverterParameter,
              InputConverterLanguage is { } ? 
                  new System.Globalization.CultureInfo(InputConverterLanguage)
                  : System.Globalization.CultureInfo.CurrentCulture);
      }
      else
      {
          resolvedParameter = parameter;
      }

      if (!Command.CanExecute(resolvedParameter))
      {
          return false;
      }

      Command.Execute(resolvedParameter);
      return true;
  }

but It isn't perfect if we need using SelectionChangedArgs. It's not a good solution.

Any have any clues about it ?