Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass command parameter from the xaml

I try to do something like this:

<DataGrid Name="myGrid" ItemSource="{Binding Path=MyCollection}">
   <DataGrid.ContextMenu>
       <ContextMenu>
          <MenuItem 
              Command="{Binding RemoveRow}" 
              CommandParameter="{Binding ElementName=myGrid, Path=SelectedItem}">
       </ContextMenu>
   </DataGridContextMenu>
</DataGrid>

but I got null always (I tried also SelectedIndex and SelectedValue)

if I pass the following parameter to the execution code, it works:

<MenuItem Command="{Binding RemoveRow}" CommandParameter="1">
like image 829
Maya Avatar asked Nov 16 '11 15:11

Maya


People also ask

How do you pass a command parameter in WPF MVVM?

Passing a parameter to the CanExecute and Execute methods A parameter can be passed through the "CommandParameter" property. Once the button is clicked the selected address value is passed to the ICommand. Execute method. The CommandParameter is sent to both CanExecute and Execute events.

What is command parameter?

The CommandParameter property is used to pass specific information to the command when it is executed. The type of the data is defined by the command. Many commands do not expect command parameters; for these commands, any command parameters passed will be ignored.

What is WPF CommandParameter?

Command - gets the command that will be executed when the command source is invoked. CommandParameter - represents a user-defined data value that can be passed to the command when it is executed. CommandTarget - the object on which the command is being executed.

What is command parameter in xamarin forms?

The ViewModel contains code associated with that ICommand property that is executed when the button is clicked. You can set CommandParameter to arbitrary data to distinguish between multiple buttons if they are all bound to the same ICommand property in the ViewModel.


2 Answers

Try something like this in your CommandParameter,

<DataGrid.ContextMenu>      <ContextMenu>            <MenuItem Header="MyHeader"                       Command="{Binding MyCommand}"                      CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}, Path=PlacementTarget.SelectedItem}" /> </DataGrid.ContextMenu> 

I already tested it and it should work.

like image 83
Rayan Elmakki Avatar answered Sep 28 '22 04:09

Rayan Elmakki


It doesn't work because the ContextMenu is not part of the visual or logical tree of the DataGrid, so it doesn't inherit the DataContext.

As far as I know, there is know easy solution to this problem using only the built-in binding system. However, using a simple "proxy" class as explained here, you can work around this problem:

<DataGrid Name="myGrid" ItemSource="{Binding Path=MyCollection}">
   <DataGrid.Resources>
       <local:BindingProxy x:Key="proxy" Data="{Binding}" />
   </DataGrid.Resources>
   <DataGrid.ContextMenu>
       <ContextMenu>
          <MenuItem 
              Command="{Binding Data.RemoveRow, Source={StaticResource proxy}}" 
              CommandParameter="{Binding ElementName=myGrid, Path=SelectedItem}">
       </ContextMenu>
   </DataGridContextMenu>
</DataGrid>

However you still have a problem: ElementName=myGrid doesn't work (again, because ContextMenu isn't in the visual or logical tree of the DataGrid, so it's not in the same name scope). A simple solution is to bind the SelectedItem of the DataGrid to a property of the ViewModel, and use that property instead of the command parameter:

<DataGrid Name="myGrid" ItemSource="{Binding Path=MyCollection}"
          SelectedItem="{Binding SelectedItem}">
   <DataGrid.Resources>
       <local:BindingProxy x:Key="proxy" Data="{Binding}" />
   </DataGrid.Resources>
   <DataGrid.ContextMenu>
       <ContextMenu>
          <MenuItem 
              Command="{Binding Data.RemoveRow, Source={StaticResource proxy}}">
       </ContextMenu>
   </DataGridContextMenu>
</DataGrid>
like image 31
Thomas Levesque Avatar answered Sep 28 '22 04:09

Thomas Levesque