[英]How do I implement a clipboard copy on a WPF DataGrid using MVVM?
我的 ViewModel 中有一个由 ObservableCollection 对象支持的 DataGrid。 我还有一个上下文菜单,其中包含使用默认复制命令的复制条目。 我希望能够从 DataGrid 复制数据,但是当我单击 Copy 菜单项时,WPF 会引发此异常:
OpenClipboard Failed (Exception from HRESULT: 0x800301D0 (CLIPBRD_E_CANT_OPEN))
视图模型
public class ViewModel
{
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public ObservableCollection<Person> People { get; set; }
public ViewModel()
{
People = new ObservableCollection<Person>
{
new Person {FirstName = "Heir", LastName = "Band"},
new Person {FirstName = "Rose", LastName = "Anne"},
new Person {FirstName = "Tim", LastName = "Poral"}
};
}
}
XAML
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.DataContext>
<local:ViewModel />
</Window.DataContext>
<Grid>
<DataGrid ItemsSource="{Binding Path=People}">
<DataGrid.ContextMenu>
<ContextMenu>
<MenuItem Header="Copy" Command="Copy" />
</ContextMenu>
</DataGrid.ContextMenu>
</DataGrid>
</Grid>
</Window>
我已经看到了这个异常的其他描述。 然而:
更多信息 - 2019 年 10 月 17 日
在Abin Mathew发布他的答案后,我做了更多的挖掘工作。 虽然他的答案是一个很好的答案,而且它有效——它不使用WPF Commanding ,而是使用 RelayCommand。 没关系。 此问题未指定必须使用 WPF 命令。
但是,我仍然想知道为什么 WPF 命令副本不适用于 DataGrid。 事实上,它确实有效——它只是取决于时间。 如果您运行我上面发布的确切代码,但在System.Windows.Clipbard.Flush
和System.Windows.Controls.DataGrid.OnExecutedCopy
处放置断点,然后每次点击断点时单击运行按钮,复制将成功:
所以总而言之:
ApplicationCommands
like Cut & Copy only act on Selection
.if you are not able to select text like in TextBox then it will throw exception.
恐怕WPF
引入了一个新Bug
例如像下面
<TextBox>
<TextBox.ContextMenu>
<ContextMenu>
<MenuItem Header="Paste" Command="ApplicationCommands.Paste" />
<MenuItem Header="Copy" Command="ApplicationCommands.Copy" />
</ContextMenu>
</TextBox.ContextMenu>
</TextBox>
您可以通过添加ICommand
和Binding
Command
来在DataGrid
上使用复制而不选择,如下所示
<MenuItem Header="Copy" Command="{Binding CopyCommand}" CommandParameter="{Binding}"
而 ViewModel 将是
public ICommand CopyCommand => new RelayCommand<object>(Copy);
private static void Copy(object obj)
{
Clipboard.SetDataObject(((ViewModel)obj).People);
}
这会将People
的集合复制到Clipboard
。 如果那是你想要做的。
希望这可以帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.