Search code examples
c#uwpcommandwindows-community-toolkit

UWP. How to pass command-parameter when ItemClickCommand of AdaptiveGridView executes?


<uwpkit:AdaptiveGridView ItemsSource="{x:Bind ViewModel.FavoriteContacts}"
                             IsItemClickEnabled="True"
                             SelectedItem="{x:Bind ViewModel.SelectedContact,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
                             ItemClickCommand="{x:Bind ViewModel.ExecuteCommand}">

</uwpkit:AdaptiveGridView>

This AdaptiveGridView show list of favorite contacts and instead of handling event ItemClick I choosed to use command. Furthermore I need to pass selected contact as command parametr. So I have found ItemClickCommand property that can help me use command. But I have not found any way that will allow me pass command parameter.

I tried to solve this problem with creating property SelectedContact and bind it to SelectedItem property of AdaptiveGridView but barrier that don't allow me to use this scenario is that execution of command runs before SelectedContact setter accessor runs. And I have null reference exception thrown.

So it was my only idea how to solve this task. If you know how to solve this task or maybe how to change order of executions of command and setter accessor of SelectedItem explain this.


Solution

  • First of all, It’s not very clear about “This AdaptiveGridView show list of favorite contacts and instead of handling event ItemClick I choosed to use command”. Does it mean “show list of favorite contacts” is only the itemsSource or when you handle ItemClick event, “the list of favorite contacts” will change? But about “pass selected contact as command parameter”,you can read the following code:

    First,in XAML:

     <uwpkit:AdaptiveGridView ItemsSource="{x:Bind ViewModel.FavoriteContacts}"
                             IsItemClickEnabled="True"
                             ItemClickCommand="{x:Bind ViewModel. ExecuteCommand}">
    

    Next,you can create command class like this:

    public class RelayCommand : ICommand
    {
        public Contact selectedContact;
        private readonly Action _execute;
        private readonly Func<bool> _canExecute;
    
        public event EventHandler CanExecuteChanged;
    
        public RelayCommand(Action execute)
            : this(execute, null)
        {
        }
    
        public RelayCommand(Action execute, Func<bool> canExecute)
        {
            if (execute == null)
                throw new ArgumentNullException("execute");
            _execute = execute;
            _canExecute = canExecute;
        }
    
        public bool CanExecute(object parameter)
        {
            return _canExecute == null ? true : _canExecute();
        }
    
        public void Execute(object parameter)
        {
            selectedContact = parameter as Contact;
            _execute();
        }
    
        public void RaiseCanExecuteChanged()
        {
            var handler = CanExecuteChanged;
            if (handler != null)
            {
                handler(this, EventArgs.Empty);
            }
        }
    }
    

    Then,in your ViewModel,you can Initialize the command class as a property:

    public RelayCommand ExecuteCommand { get; set; }
    

    ,this property is binded to “ItemClickCommand” in XAML.Also,you can initialize the ExecuteCommand and pass the MyItemClick event to the command:

    public ContactViewModel() { ExecuteCommand = new RelayCommand(MyItemClick); }
    

    in your ViewModel’s constructor.

    Last,you can see the command has a “public void Execute(object parameter)” method . It has one parameter, which can be used to pass the information binded with the UIElement from the caller to the command. It means when you click the item,it will be triggered and the “Contact” object will be passed by this method.Then you can save it.So,when you click the item,the “MyItemClick” method will be triggered and you can use the Contact object you saved in the Execute method,for example:

        private void MyItemClick(){
        Contact contact = ExecuteCommand.selectedContact;
        //do something when clicked
    }
    

    If you still have the problem, please share more details about your code, like a reproduce-able demo.