DataGridTextColumnでコピー時エラーへの対処
xamlでDataGridTextColumnを作って、セルを1回クリックして選択状態にし、Ctrl+Cでコピーすると、例外が発生して落ちました。
詳細は以下のような例外でした。
System.Runtime.InteropServices.COMException はハンドルされませんでした。 HResult=-2147221040 Message=OpenClipboard に失敗しました (HRESULT からの例外:0x800401D0 (CLIPBRD_E_CANT_OPEN)) Source=mscorlib ErrorCode=-2147221040 StackTrace: 場所 System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo) 場所 System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(Int32 errorCode, IntPtr errorInfo) 場所 System.Windows.Clipboard.Flush() 場所 System.Windows.Clipboard.CriticalSetDataObject(Object data, Boolean copy) 場所 System.Windows.Controls.DataGrid.OnExecutedCopy(ExecutedRoutedEventArgs args) 場所 System.Windows.Controls.DataGrid.OnExecutedCopy(Object target, ExecutedRoutedEventArgs args) 場所 System.Windows.Input.CommandBinding.OnExecuted(Object sender, ExecutedRoutedEventArgs e) 場所 System.Windows.Input.CommandManager.ExecuteCommandBinding(Object sender, ExecutedRoutedEventArgs e, CommandBinding commandBinding) 場所 System.Windows.Input.CommandManager.FindCommandBinding(Object sender, RoutedEventArgs e, ICommand command, Boolean execute) 場所 System.Windows.Input.CommandManager.OnExecuted(Object sender, ExecutedRoutedEventArgs e) 場所 System.Windows.UIElement.OnExecutedThunk(Object sender, ExecutedRoutedEventArgs e) 場所 System.Windows.Input.ExecutedRoutedEventArgs.InvokeEventHandler(Delegate genericHandler, Object target) 場所 System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target) 場所 System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs) 場所 System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised) 場所 System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args) 場所 System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args) 場所 System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted) 場所 System.Windows.Input.RoutedCommand.ExecuteImpl(Object parameter, IInputElement target, Boolean userInitiated) 場所 System.Windows.Input.RoutedCommand.ExecuteCore(Object parameter, IInputElement target, Boolean userInitiated) 場所 System.Windows.Input.CommandManager.TranslateInput(IInputElement targetElement, InputEventArgs inputEventArgs) 場所 System.Windows.UIElement.OnKeyDownThunk(Object sender, KeyEventArgs e) 場所 System.Windows.Input.KeyEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget) 場所 System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target) 場所 System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs) 場所 System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised) 場所 System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args) 場所 System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args) 場所 System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted) 場所 System.Windows.Input.InputManager.ProcessStagingArea() 場所 System.Windows.Input.InputManager.ProcessInput(InputEventArgs input) 場所 System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport) 場所 System.Windows.Interop.HwndKeyboardInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawKeyboardActions actions, Int32 scanCode, Boolean isExtendedKey, Boolean isSystemKey, Int32 virtualKey) 場所 System.Windows.Interop.HwndKeyboardInputProvider.ProcessKeyAction(MSG& msg, Boolean& handled) 場所 System.Windows.Interop.HwndSource.CriticalTranslateAccelerator(MSG& msg, ModifierKeys modifiers) 場所 System.Windows.Interop.HwndSource.OnPreprocessMessage(Object param) 場所 System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs) 場所 MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler) 以下略
原因はインストールしていたCLCLというコピー履歴を保持するソフトと思われます。
おそらくクリップボードへのコピーが競合して、DataGridTextColumnでのコピー時にClipboard.Flush()が失敗したことが原因ではないでしょうか。
DataGridを扱うときにはコピー履歴をとるようなソフトは使わないほうがいいんでしょうね。
ただ、併用したい場合もあるでしょうから、とりあえず以下のサイトを参考に例外が起きないようにします。stackoverflow.com
まず、以下のようにApp.xamlにApplication_DispatcherUnhandledExceptionイベントを設定します。
これで未定義の例外をキャッチできるようにします。
<Application x:Class="AnimeCheckerByXaml.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" StartupUri="MainWindow.xaml" DispatcherUnhandledException="Application_DispatcherUnhandledException"> <Application.Resources> </Application.Resources> </Application>
次にApp.xaml.csでこのイベントを記述し、DispatcherUnhandledExceptionEventArgsの例外をクリップボードエラーのエラーコードを指定することで決め打ちで処理しています。
void Application_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) { var comException = e.Exception as System.Runtime.InteropServices.COMException; if (comException != null && comException.ErrorCode == -2147221040) e.Handled = true; }