Mr J
Mr J

Reputation: 2965

Right click and copy content menu on c# WPF datagrid

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>

Upvotes: 3

Views: 5056

Answers (1)

grek40
grek40

Reputation: 13438

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;
    }
}

Upvotes: 3

Related Questions