У меня есть DataGrid, поддерживаемый ObservableCollection объектов в моей ViewModel. У меня также есть контекстное меню с записью «Копировать», в которой используется команда «Копировать» по умолчанию. Я хотел бы иметь возможность копировать данные из DataGrid , но когда я нажимаю на пункт меню Копировать, WPF выдает это исключение:
OpenClipboard Failed (Exception from HRESULT: 0x800301D0 (CLIPBRD_E_CANT_OPEN))
ViewModel
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>
Я видел другие описания этого исключения . Однако:
- Я использую Visual Studio 2017, а не 2019.
- Я не использую SetText или SetDataObject, или не вызываю что-либо по этому вопросу.
- Исключение происходит каждый раз, не периодически, независимо от того, запущен ли я из Visual Studio или нет.
- Меня не интересует выделенный код, такой как "myDataGrid_CopyingRowClipboardContent", так как я использую MVVM.
Дополнительная информация - 10/17/2019
Я сделал еще несколько копаний после Абин Мэтью опубликовано его ответ . Хотя его ответ отличный, и он работает - он не использует WPF Commanding , а скорее использует RelayCommand. Все в порядке. Этот вопрос не указывает, что WPF Commanding должен использоваться.
Однако я все еще хотел знать, почему WPF Commanding Copy не работает для DataGrid. На самом деле, это работает - это зависит только от времени. Если вы запустили точный код, который я разместил выше, но поставили точки останова на System.Windows.Clipbard.Flush
и System.Windows.Controls.DataGrid.OnExecutedCopy
, а затем нажимали кнопку запуска при каждом нажатии на точки останова, копирование выполнится успешно:
Итак, в заключение:
- RelayCommand работает для выполнения копирования.
- Командование WPF также "работает".
- WPF Commanding управляет получением данных, предназначенных для буфера обмена, из самих выбранных строк DataGrid.
- Происходит какое-то состояние гонки, которое приводит к тому, что WPF Commanding не может получить доступ к очистке буфера обмена при копировании из DataGrid. .
- Либо мне нужно больше кода для предотвращения этого состояния гонки, либо Microsoft представила ошибку, нарушающую WPF Commanding Copy из DataGrid.