3

So I have a WPF data grid with about 8 cells in each row, I've only included the relevant one for simplicity but I'd like the user to be able to right click this cell and copy the contents into the windows clipboard without left clicking and selecting it first. I've tried many code snippets but can't seem to get anything to work. Each row is a binded item.

The majority of things I've been trying is with the MouseRightButtonDown event. Some have tried the to the XY position, some have used e.OriginalSource as FrameworkElement but I can't seem to get anything to work. Not sure if its because its a DataGridHyperlinkColumn as opposed to the other types used in the examples?

I'm a c# n00b! Any help would be greatly appreciated.

    <DataGrid x:Name="eventsDataGrid" AutoGenerateColumns="False" IsReadOnly="true" ItemsSource="{Binding}" HorizontalAlignment="Left" Margin="10,143,0,0" VerticalAlignment="Top" Height="295"  CanUserAddRows="False" CanUserReorderColumns="False" CanUserResizeColumns="True" CanUserSortColumns="False" BorderThickness="1" HorizontalScrollBarVisibility="Disabled"  FontSize="10" Width="1003" MouseRightButtonDown="eventsDataGrid_MouseRightButtonDown">

        <DataGrid.ContextMenu>
            <ContextMenu>
                <MenuItem Header="Copy URL" Click="CopyURL">
                </MenuItem>
            </ContextMenu>
        </DataGrid.ContextMenu>

        <DataGrid.Columns>

            <DataGridHyperlinkColumn Width="230" Header="URL" Binding="{Binding URL}"  CanUserResize="False">
                <DataGridHyperlinkColumn.HeaderStyle>
                    <Style TargetType="{x:Type DataGridColumnHeader}">
                        <Setter Property="ToolTip" Value="URL of website" />
                        <Setter Property="HorizontalContentAlignment" Value="Center"/>
                        <Setter Property="VerticalAlignment" Value="Center"/>
                    </Style>
                </DataGridHyperlinkColumn.HeaderStyle>

                <DataGridHyperlinkColumn.CellStyle>
                    <Style TargetType="{x:Type DataGridCell}">
                        <Setter Property="Foreground" Value="Black" />
                        <Setter Property="HorizontalAlignment" Value="Center"/>
                        <Setter Property="FontSize" Value="12"/>
                    </Style>
                </DataGridHyperlinkColumn.CellStyle>
            </DataGridHyperlinkColumn>

        </DataGrid.Columns>
    </DataGrid>
3
  • 1
    You could assign your context menu to the cells instead of the DataGrid and use Command with CommandParameter instead of the Click event. By passing the cell content as command parameter, everything should be available to fill the clipboard in the code behind. Commented Jul 12, 2016 at 13:07
  • Thanks man, that sounds like exactly what I need however I can't figure out how to assign my context menu to the cells, which part of the XAML would the <ContextMenu> now go in? I tried it inside DataGridHyperlinkColumn and DataGridHyperlinkColumn.CellStyle, didn't seem it like it and I can't find any web examples. Any idea? Commented Jul 12, 2016 at 13:51
  • 1
    stackoverflow.com/questions/5200687/… Just a few modifications is needed to pass the item as a command parameter Commented Jul 12, 2016 at 14:06

1 Answer 1

3

The following example shows how to use a single context menu as resource for multiple target elements. Note that it might be a good idea to create a custom command instead of 'borrowing' ApplicationCommands.Copy for the purpose of demonstration, as I did here.

<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"
        Loaded="Window_Loaded">
    <Window.CommandBindings>
        <CommandBinding Command="ApplicationCommands.Copy"
                        Executed="CopyCommand_Executed"
                        CanExecute="CopyCommand_CanExecute"/>
    </Window.CommandBindings>
    <Window.Resources>
        <ContextMenu x:Key="ctMenu" DataContext="{Binding PlacementTarget,RelativeSource={RelativeSource Self}}">
            <MenuItem Header="Copy URL"
                      Command="ApplicationCommands.Copy"
                      CommandTarget="{Binding}"
                      CommandParameter="{Binding Text}"/>
        </ContextMenu>
    </Window.Resources>
    <StackPanel>
        <TextBlock Text="123" ContextMenu="{StaticResource ctMenu}"/>
        <TextBlock Text="456" ContextMenu="{StaticResource ctMenu}"/>
    </StackPanel>
</Window>

The command binding also needs some code behind (will be different with a custom command implementation)

private void CopyCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
    Clipboard.SetText(e.Parameter as string);
}

private void CopyCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
    if (!string.IsNullOrEmpty(e.Parameter as string))
    {
        e.CanExecute = true;
        e.Handled = true;
    }
}
Sign up to request clarification or add additional context in comments.

5 Comments

Thank you for your response but this code seems to behave in the same way as my original code. When I right click a row the copy menu appears but is grayed out and when I left click a row (so its selected) then right click it the copy menu appears and the content can be copied to the clipboard. Was the expected? Apologies if I didn't explain my desired outcome accurately :-)
I'm adding ContextMenu="{StaticResource ctMenu}" to my <DataGrid x:Name="eventsDataGrid">. Is that correct?
No, you should add it to the cells / cell contents via style or template. See comment from @michauzo for more details.
But Ctrl+C not working.
@SandeepJadhav since this whole thing is 7 years old, I suggest you create your own question with all relevant details, if you have a related problem that can't be solved with existing question/answer entries.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.