0

I am a bit confused about ICommand and RelayCommand

If I do this on an autocomplete control

public RelayCommand<KeyEventArgs> AutoCompleteCommand
{
    get;
    private set;
}

public MyConstructor()
{        
    AutoCompleteCommand = new RelayCommand<KeyEventArgs>((e) =>
    {
        //Check if the key pressed is <Enter>
        //if it is, check also if the SearchPropertyValue is not String.Empty then
        var d = e;

        //Should it return true or false?                      
    });
}

In the Xaml:

<toolkit:AutoCompleteBox x:Name="acbStore" Margin="154,196,29,0" VerticalAlignment="Top" RenderTransformOrigin="0.6,0.083" Height="162"/>


<i:Interaction.Triggers>
    <i:EventTrigger EventName="KeyDown">
        <GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding AutoCompleteCommand, Mode=OneWay}" PassEventArgsToCommand="True"/>
    </i:EventTrigger>
</i:Interaction.Triggers>

Nothing happens.

If I do this

public ICommand AutoComplete
{
    get
    {
        return new RelayCommand<KeyEventArgs>(e =>
        {
            var key = e.Key;
        });
    }
}

In the Xaml:

<i:Interaction.Triggers>
    <i:EventTrigger EventName="KeyDown">
        <GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding AutoComplete, Mode=OneWay}" 
            PassEventArgsToCommand="True"/>
    </i:EventTrigger>
</i:Interaction.Triggers>

<toolkit:AutoCompleteBox x:Name="acbStore" Margin="154,196,29,0" 
    VerticalAlignment="Top" RenderTransformOrigin="0.6,0.083" Height="162"/>

It works and my command is triggered.

Also from all the examples I seen the RelayCommand always seems to go in the constructor. Can I stick it anywhere else as it is going to make the constructor very cluttered.

Noctis
  • 11,507
  • 3
  • 43
  • 82
chobo2
  • 83,322
  • 195
  • 530
  • 832
  • 1
    You are not binding the command in your first sample so it won't trigger. Whether you use `ICommand` or `RelayCommand<>` you still have to bind it in your xaml. – Alaa Masoud Jun 05 '13 at 00:58
  • The RelayCommand is an object like any other. You can instantiate it wherever you want, but it needs to be instantiated, and it needs to be bound to your XAML somewhere. – LBugnion Jun 05 '13 at 09:01
  • @AlaaMasoud - Sorry it is actually there but I guess I did not highlight it with the "code formatter" so it was not being shown. – chobo2 Jun 05 '13 at 16:31
  • @LBugnion - Well should I put the code in the constructor in maybe the getter of the RelayCommand? – chobo2 Jun 05 '13 at 16:34

1 Answers1

0

Regarding the problem, both should work really. (one of the comments said it's not bound in the first example, but your code suggests it is. Maybe it has to do with how things are set? In any case, the second approach returns a new one every call, which smells a bit to be honest...

About the where to do it, you can do it either way. I've seen 2 main approaches:

First option:
Have a private ICommand as property, and define it in Constructor:

ctor {
    Cool_Command =  new RelayCommand<EventArgs>(Execute_CoolCommand, 
                                                CanExecute_CoolCommand);    
}

public ICommand Cool_Command { get; private set; }

Second option:
Have it as property which is set the first time it's called.

public ICommand CoolAsWell_Command
{
    get
    {
        return _coolAsWellCommand ??
             (_coolAsWellCommand = 
                new RelayCommand<EventArgs>(Execute_CoolAsWell, 
                                            CanExecute_CoolAsWell));
    }
    private set { _coolAsWellCommand = value; }
}
private ICommand _coolAsWellCommand;

Regarding which is better: Which are prettier, redheads, or blonds? :)

Noctis
  • 11,507
  • 3
  • 43
  • 82