Here is the layout sketch of my application:
<UserControl>
<Grid>
<Grid.ColumnDefinitions>...</Grid.ColumnDefinitions>
<Grid.RowDefinitions>...</Grid.RowDefinitions>
<Border>...</Border>
<Grid>...</Grid>
<DataGrid Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="2" AutoGenerateColumns="False"
HorizontalAlignment="Stretch" Name="myDataGrid" VerticalAlignment="Stretch"
ItemsSource="{Binding Path=MyModel.Files}"
SelectedItem="{Binding SelectedFile}"
Margin="0,0,10,3" CanUserReorderColumns="False" CanUserResizeRows="False" Style="{StaticResource DataGridStyle_Generic}"
IsReadOnly="True">...</DataGrid.ContextMenu>
</DataGrid>
<Border>...</Border>
<Border BorderBrush="Gray" BorderThickness="1" Grid.Row="4" Grid.Column="1" Grid.ColumnSpan="2" Margin="0,0,10,0">
<Grid Margin="0,0,10,0">
<Grid.ColumnDefinitions>...</Grid.ColumnDefinitions>
<Grid.RowDefinitions>...</Grid.RowDefinitions>
<StackPanel Grid.Row="1" Orientation="Horizontal" Margin="0,0,10,2">
<Button>...</Button>
<Button Margin="0" Name="m_DropDownButton" Padding="0, 4"
HorizontalAlignment="Center" VerticalAlignment="Center"
ContextMenuService.IsEnabled="False" Click="m_DropDownButton_Click">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
<Path x:Name="BtnArrow" Margin="4" VerticalAlignment="Center" Width="6" Fill="#FF000000" Stretch="Uniform" HorizontalAlignment="Right" Data="F1 M 301.14,-189.041L 311.57,-189.041L 306.355,-182.942L 301.14,-189.041 Z "/>
</StackPanel>
<Button.ContextMenu>
<ContextMenu>
<MenuItem Header="All files" Command="{Binding AllFilesCommand}" />
<MenuItem Header="Selected files only"
Command="{Binding SelectedFilesOnlyCommand}"
CommandParameter="{Binding Path=SelectedItems, ElementName=myDataGrid}"/>
</ContextMenu>
</Button.ContextMenu>
</Button>
</StackPanel>
<StackPanel Grid.Row="0" Orientation="Horizontal" VerticalAlignment="Stretch" Margin="0,0,10,0">...</StackPanel>
</Grid>
</Border>
</Grid>
</UserControl>
I'd like to pass the SelectedItems
property of myDataGrid
as a CommandParameter in myMenuItem
's Command. How can I achieve this?
Note #1: These two controls are located far in the Visual Tree and their first common parent is myGrid
. Couldn't find any working solution for this because I'm always getting the "Cannot find source for binding" error message in the output window.
Note #2: The SelectedItems
property of DataGrid is readonly therefore it is not allowed to bind it to a ViewModel property.
Note #3: I'd like to avoid any code behind code such as creating an event handler for DataGrid's SelectionChanged
event.
I did not try the Sheridan's way, and it's worth a read IMHO.
Anyway, you may also try the below hack:
<Button Margin="0" Name="m_DropDownButton" Padding="0, 4"
HorizontalAlignment="Center" VerticalAlignment="Center"
ContextMenuService.IsEnabled="False" Click="m_DropDownButton_Click"
Tag="{Binding ElementName=myDataGrid}"
>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
<Path x:Name="BtnArrow" Margin="4" VerticalAlignment="Center" Width="6" Fill="#FF000000" Stretch="Uniform" HorizontalAlignment="Right" Data="F1 M 301.14,-189.041L 311.57,-189.041L 306.355,-182.942L 301.14,-189.041 Z "/>
</StackPanel>
<Button.ContextMenu>
<ContextMenu>
<MenuItem Header="All files" Command="{Binding AllFilesCommand}" />
<MenuItem Header="Selected files only"
Command="{Binding SelectedFilesOnlyCommand}"
CommandParameter="{Binding Path=PlacementTarget.Tag.SelectedItems, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}}"/>
</ContextMenu>
</Button.ContextMenu>
</Button>
Note the "Tag" attribute on the button and the CommandParameter binding.
There's also a little code-behind, but I believe you have it as well:
private void m_DropDownButton_Click(object sender, RoutedEventArgs e)
{
var button = (Button)sender;
button.ContextMenu.PlacementTarget = button;
button.ContextMenu.IsOpen = true;
}
Let me know.