将 ContextMenu 绑定到 DataGridCell 内容以复制内容

Binding ContextMenu to DataGridCell Content To Copy Content

我以前做过 ContextMenus,但对于 DataGrid,它们似乎太复杂了。我只想将单元格的内容复制到剪贴板中。我怎样才能让这个工作?似乎有很多选择,但没有固定的保证方法。

<DataGrid ItemsSource="{Binding MyStuff}">
      <DataGridTextColumn Binding="{Binding MyContentIWantToCopy}">
          <DataGridTextColumn.CellStyle>
              <Setter Property="ContextMenu">
                                <Setter.Value>
                                    <ContextMenu>
                                        <MenuItem Command="ApplicationCommands.Copy"/>
                                    </ContextMenu>
                                </Setter.Value>
                            </Setter>
          <DataGridTextColumn.CellStyle>
      </DataGridTextColumn>
</DataGrid>

理想情况下,这是最简单的方法。但是,当然,它不起作用。

但是,我也尝试过命令 -

Paste from Excel to WPF DataGrid

MVVM binding command to contextmenu item

Create contextmenus for datagrid rows

None 这些作品。通常结果是出现一个上下文菜单和一个灰色按钮或一个不执行任何操作的按钮,永远不会触发命令。我只想将 Datagrid 单元格内的文本复制到剪贴板中。我之前以类似的方式在各种对象上完成过此操作 - 甚至是 Listviews - 但我找不到 DataGrid 和 DataGridTextColumns 的任何解决方案。

您的 xaml 消息开头的代码 - 包含错误。但即使在修复之后,它似乎也需要复制整行而不是一个单元格。

一种直接的变体 - 只需编写自己的命令,例如:

public class MyCopyCommand : ICommand
{
    public string Name { get { return "Copy"; } }

    public void Execute(object parameter)
    {
        Clipboard.SetText(parameter != null ? parameter.ToString() : "<null>");
    }

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public event EventHandler CanExecuteChanged;
}

此命令认为参数已包含需要复制的字符串。但是您可以根据需要自定义它的逻辑,例如 - 获取整个 DataGridCell 并决定 - 从中​​复制什么。 第二步 - 使用我们在 XAML 中的命令,例如通过资源:

<Window 
x:Class="WpfApplication65.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"

xmlns:app="clr-namespace:WpfApplication65"
>
<Window.Resources>
    <app:MyCopyCommand x:Key="CopyCommand"/>
</Window.Resources>
<Grid>
    <DataGrid x:Name="MyDataGrid">
        <DataGrid.CellStyle>
            <Style TargetType="{x:Type DataGridCell}">
                <Setter Property="ContextMenu">
                    <Setter.Value>
                        <ContextMenu>
                            <MenuItem 
                                Command="{StaticResource CopyCommand}" 
                                CommandParameter="{Binding Path=Parent.PlacementTarget.Content.Text, RelativeSource={RelativeSource Self}}"
                                Header="{Binding Name, Source={StaticResource CopyCommand}}"
                                />
                        </ContextMenu>
                    </Setter.Value>
                </Setter>
            </Style>
        </DataGrid.CellStyle>
    </DataGrid>
</Grid>

其中 "WpfApplication65" 只是我的项目名称,您当然必须插入您的项目名称。 在这里,我按原样编写了 CommandParameter 绑定路径,因为我知道,DataGrid 将自动生成带有 TextBlock 的 DataGridCell,其内容 属性。如果您想要通用解决方案 - 将 CommandParameter 绑定到 Parent.PlacementTarget ,您将获得 DataGridCell 实例到您的 MyCopyCommand.Execute 方法,然后使用它和它的 Column 属性 - 从中​​获取您想要的东西。

并使我们的 DataGrid 工作 - 添加到 MainWindow class 此代码:

public class MyData
{
    public string Name { get; set; }
    public int Count { get; set; }
    public MyData(string name, int count)
    {
        Name = name;
        Count = count;
    }
}

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        var data = new List<MyData>
            {
                new MyData("one", 10), 
                new MyData("two", 100500), 
                new MyData("three", 777)
            };
        MyDataGrid.ItemsSource = data;
    }
}

希望这对您有所帮助,如果有什么不对,请问我。

XAML:

<DataGrid x:Name="MyDataGrid">
  <DataGridTextColumn Binding="{Binding MyContentIWantToCopy}">
    <DataGrid.CellStyle>
      <Style TargetType="{x:Type DataGridCell}">
        <Setter Property="ContextMenu">
          <Setter.Value>
            <ContextMenu>
              <MenuItem Header="Copy" Click="MenuItem_OnClick"/>
            </ContextMenu>
          </Setter.Value>
        </Setter>
      </Style>
    </DataGrid.CelStyle>
  </DataGridTextColumn>
</DataGrid>

代码隐藏:

void MenuItem_OnClick(object sender, RoutedEventArgs e)
{
  ApplicationCommands.Copy.Execute(null, MyDataGrid);
}

我认为您也可以在 XAML 中使用属性 CommandTarget,而不是使用代码隐藏。