【问题标题】:Binding ContextMenu to DataGridCell Content To Copy Content将 ContextMenu 绑定到 DataGridCell 内容以复制内容
【发布时间】:2015-04-08 23:18:08
【问题描述】:

我以前做过 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

这些都不起作用。通常,结果是出现一个上下文菜单,并且要么是灰色按钮,要么是不执行任何操作的按钮,从不触发命令。我只想将 Datagrid 单元格中的文本复制到剪贴板中。我以前以类似的方式对各种对象进行过此操作 - 甚至是 Listviews - 但我找不到 DataGrid 和 DataGridTextColumns 的任何解决方案。

【问题讨论】:

    标签: c# wpf mvvm datagrid


    【解决方案1】:

    您在消息开头的 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 将在其 Content 属性中自动生成带有 TextBlock 的 DataGridCell。如果您想要通用解决方案 - 将 CommandParameter 绑定到 Parent.PlacementTarget,您将获得 DataGridCell 实例到您的 MyCopyCommand.Execute 方法,然后使用它和它的 Column 属性 - 从中​​获取您想要的。

    为了使我们的 DataGrid 正常工作 - 将这段代码添加到 MainWindow 类:

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

    希望这会有所帮助,如果某些东西不起作用 - 问我。

    【讨论】:

      【解决方案2】:

      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,而不是使用代码隐藏。

      【讨论】:

        猜你喜欢
        • 2011-03-30
        • 1970-01-01
        • 1970-01-01
        • 2011-05-22
        • 2019-01-18
        • 1970-01-01
        • 1970-01-01
        • 2011-09-04
        • 1970-01-01
        相关资源
        最近更新 更多