Ich habe eine WPF-Anwendung mit Datagrid. Die Anwendung funktionierte einwandfrei, bis ich Visual Studio 2012 und Blend + SketchFlow Preview installiert hatte. Wenn ich jetzt versuche, die Daten aus dem Raster mit Ctrl+ C(in einer beliebigen Anwendung) in die Zwischenablage zu kopieren , wird die folgende Ausnahme angezeigt:
System.Runtime.InteropServices.COMException (0x800401D0): OpenClipboard Failed (Exception from HRESULT: 0x800401D0 (CLIPBRD_E_CANT_OPEN))
at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)
at System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(Int32 errorCode, IntPtr errorInfo)
at System.Windows.Clipboard.Flush()
at System.Windows.Clipboard.CriticalSetDataObject(Object data, Boolean copy)
at System.Windows.Controls.DataGrid.OnExecutedCopy(ExecutedRoutedEventArgs args)
at System.Windows.Controls.DataGrid.OnExecutedCopy(Object target, ExecutedRoutedEventArgs args)
at System.Windows.Input.CommandBinding.OnExecuted(Object sender, ExecutedRoutedEventArgs e)
at System.Windows.Input.CommandManager.ExecuteCommandBinding(Object sender, ExecutedRoutedEventArgs e, CommandBinding commandBinding)
at System.Windows.Input.CommandManager.FindCommandBinding(CommandBindingCollection commandBindings, Object sender, RoutedEventArgs e, ICommand command, Boolean execute)
at System.Windows.Input.CommandManager.FindCommandBinding(Object sender, RoutedEventArgs e, ICommand command, Boolean execute)
at System.Windows.Input.CommandManager.OnExecuted(Object sender, ExecutedRoutedEventArgs e)
at System.Windows.UIElement.OnExecutedThunk(Object sender, ExecutedRoutedEventArgs e)
at System.Windows.Input.ExecutedRoutedEventArgs.InvokeEventHandler(Delegate genericHandler, Object target)
at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
at System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)
at System.Windows.Input.RoutedCommand.ExecuteImpl(Object parameter, IInputElement target, Boolean userInitiated)
at System.Windows.Input.RoutedCommand.ExecuteCore(Object parameter, IInputElement target, Boolean userInitiated)
at System.Windows.Input.CommandManager.TranslateInput(IInputElement targetElement, InputEventArgs inputEventArgs)
at System.Windows.UIElement.OnKeyDownThunk(Object sender, KeyEventArgs e)
at System.Windows.Input.KeyEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
at System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)
at System.Windows.Input.InputManager.ProcessStagingArea()
at System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)
at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)
at System.Windows.Interop.HwndKeyboardInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawKeyboardActions actions, Int32 scanCode, Boolean isExtendedKey, Boolean isSystemKey, Int32 virtualKey)
at System.Windows.Interop.HwndKeyboardInputProvider.ProcessKeyAction(MSG& msg, Boolean& handled)
at System.Windows.Interop.HwndSource.CriticalTranslateAccelerator(MSG& msg, ModifierKeys modifiers)
at System.Windows.Interop.HwndSource.OnPreprocessMessage(Object param)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
at System.Windows.Threading.Dispatcher.Invoke(DispatcherPriority priority, Delegate method, Object arg)
at System.Windows.Interop.HwndSource.OnPreprocessMessageThunk(MSG& msg, Boolean& handled)
at System.Windows.Interop.HwndSource.WeakEventPreprocessMessage.OnPreprocessMessage(MSG& msg, Boolean& handled)
at System.Windows.Interop.ComponentDispatcherThread.RaiseThreadMessage(MSG& msg)
at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
at System.Windows.Threading.Dispatcher.Run()
at System.Windows.Application.RunDispatcher(Object ignore)
at System.Windows.Application.RunInternal(Window window)
at System.Windows.Application.Run(Window window)
at System.Windows.Application.Run()
Das ist wirklich nervig.
Ich habe hier und an verschiedenen Stellen im Internet einige Hinweise auf dieses Problem gesehen , ohne echte Lösung.
Ich kann überprüfen, ob die Zwischenablage gesperrt ist, wenn diese Ausnahme in Visual Studio ausgelöst wird, da ich die Nachricht nicht kopieren und einfügen konnte (musste sie in eine Datei schreiben). Außerdem wurde die Zwischenablage vor dem Start des Kopiervorgangs nicht gesperrt.
Wie kann man dieses Problem lösen?
Antworten:
Wir verwenden .NET 4.0. Wir hatten das gleiche Problem, aber nach dem Abmelden vom System funktionierte der Code einige Zeit einwandfrei.
Endlich haben wir die Alternative gefunden.
Wenn Sie eine Zeichenfolge in die Zwischenablage kopieren möchten,
string data = "Copy This"
Bis jetzt habe ich die folgende Methode angewendet
Es scheiterte immer wieder. Dann habe ich mir andere Methoden zum Festlegen von Text in der Zwischenablage in der Zwischenablageklasse angesehen und Folgendes versucht:
Und es hat funktioniert :). Ich hatte das Problem nie wieder.
quelle
Es ist ein Fehler im WPF-Zwischenablage-Handler. Sie müssen die nicht behandelte Ausnahme im Application.DispatcherUnhandledException-Ereignis behandeln.
Fügen Sie dieses Attribut dem
Application
Element in Ihrer App.xaml hinzuDispatcherUnhandledException="Application_DispatcherUnhandledException"
Fügen Sie diesen Code Ihrer App.xaml.cs-Datei hinzu
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; }
quelle
Application.DispatcherUnhandledException
Ereignis von einer anderen Stelle aus abonnieren, dies sollten Sie jedoch in Ihrer App-Klasse tun, wenn Ihre App geladen wird. Weitere Infos hierIch hatte auch ein Problem in einer Anwendung, in der ich Informationen in die Zwischenablage kopiere, während Benutzer eine ListBox lesen. Die Informationen, die kopiert werden, beziehen sich auf das ausgewählte Element und ermöglichen es ihnen, diese (diese Informationen) der Einfachheit halber in andere Anwendungen einzufügen. Gelegentlich erhalte ich CLIPBRD_E_CANT_OPEN auf einigen Benutzersystemen, auf anderen jedoch nicht.
Obwohl ich den Konflikt immer noch nicht beheben konnte , konnte ich Code erstellen, um die Anwendung zu finden, die den Konflikt verursacht. Ich möchte diesen Code zumindest in der Hoffnung teilen, dass er jemandem hilft. Ich werde die using- Anweisung, die Attribute und die Methode hinzufügen, die ich erstellt habe, um das Process- Objekt des Täters zu finden. Aus dem Prozesspunkt können Sie den Prozess Namen, PID, Hauptfenstertitel erhalten (wenn sie eine hat) und andere potenziell nützliche Daten. Hier sind die Codezeilen, die ich ohne den Code hinzugefügt habe, der sie aufruft. ( HINWEIS: Unter dem Code-Snippet habe ich noch einen Leckerbissen zum Teilen):
using System.Diagnostics; // For Process class using System.Runtime.InteropServices; // For DllImport's
...
[System.Runtime.InteropServices.DllImport("user32.dll")] static extern IntPtr GetOpenClipboardWindow(); [DllImport("user32.dll", SetLastError = true)] static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
...
///----------------------------------------------------------------------------- /// <summary> /// Gets the Process that's holding the clipboard /// </summary> /// <returns>A Process object holding the clipboard, or null</returns> ///----------------------------------------------------------------------------- public Process ProcessHoldingClipboard() { Process theProc = null; IntPtr hwnd = GetOpenClipboardWindow(); if (hwnd != IntPtr.Zero) { uint processId; uint threadId = GetWindowThreadProcessId(hwnd, out processId); Process[] procs = Process.GetProcesses(); foreach (Process proc in procs) { IntPtr handle = proc.MainWindowHandle; if (handle == hwnd) { theProc = proc; } else if (processId == proc.Id) { theProc = proc; } } } return theProc; }
SONSTIGER HINWEIS: Eine andere Sache, die ich geändert habe, um meinen Code ein wenig zu vereinfachen, war die Konvertierung von System.Windows.Clipboard zu System.Windows.Forms.Clipboard (siehe System.Windows.Forms.Clipboard-Klasse ), da letztere eine 4- Klasse hat. Parameter SetDataObject () -Methode, die eine Wiederholungsanzahl und eine Wiederholungsverzögerung in Millisekunden enthält. Das zumindest einen Teil der Wiederholungs entfernt Rauschen von meinem Code.
Ihr Kilometerstand kann variieren ... und es kann Nebenwirkungen geben, auf die ich noch nicht gestoßen bin. Wenn also jemand davon weiß, kommentieren Sie dies bitte. Auf jeden Fall hoffe ich, dass sich dies für jemanden als nützlich erweist.
quelle
Ich hatte dieses Problem auch in WPF 4.0 und 4.5, seit ich TeraCopy (Windows 7, 64-Bit) installiert habe . Jede Zwischenablage.SetText () ist mit einer System.Runtime.InteropServices.COMException fehlgeschlagen.
Meine erste Lösung bestand darin, TeraCopy zu deinstallieren - es hat funktioniert, aber ich liebe diese Anwendung, daher musste ich nach einer anderen Lösung suchen, um dieses Problem zu beheben. Die Lösung war zu ersetzen
Clipboard.SetText("my string");
mit
Clipboard.SetDataObject("my string");
quelle
Ich hatte das gleiche Problem mit RichTextBox. Der folgende Code stürzte zufällig ab:
TextRange tr = new TextRange(rich.Document.ContentStart, rich.Document.ContentEnd); System.Windows.Clipboard.SetDataObject(tr.Text);
Es scheint bevorzugt zu sein, System.Windows.Controls.RichTextBox.Copy zu verwenden
quelle
Ich hatte ein Problem beim Abrufen von XAML-Daten aus der Zwischenablage mit .NET 4.6.1.
Fehlermeldung:
Ich habe es wie folgt gelöst:
int counter = 0; object xamlClipData = null; while (xamlClipData == null) { try { if (counter > 10) { System.Windows.MessageBox.Show("No access to clipboard xaml data."); break; } counter++; if (System.Windows.Clipboard.GetDataObject().GetDataPresent(DataFormats.Xaml)) { xamlClipData = System.Windows.Clipboard.GetData(DataFormats.Xaml); } } catch { } }
quelle
Ich hatte das gleiche Problem beim Kopieren von Excel-Zellen in die Zwischenablage und beim Abrufen von Daten aus der Zwischenablage als HTML-Zeichenfolge.
Sie können (while-try-catch) wie im folgenden Code verwenden.
Excel.Application exap = new Microsoft.Office.Interop.Excel.Application(); Excel.Workbook wb = exap.Workbooks.Open( sourceFileNameTextBox.Text, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing); Excel.Sheets sh = wb.Worksheets; bool clip = false; // Copy Excel cells to clipboard while (!clip) { try { ws.Cells.get_Range(cells[0], cells[1]).Copy(Type.Missing); clip = true; } catch { clip = false; } } string b = ""; // Get Excel cells data from the clipboard as HTML clip = false; while(!clip) { try { b = Clipboard.GetData(DataFormats.Html) as string; clip = true; } catch { clip = false; } }
Sie können auch einen Zähler in der
while
Ausnahme haben, wenn die Schleife mehr als zehnmal oder öfter ist. Ich teste seinen maximalen Zähler ist eine und in einer Zeitschleife Zwischenablage Arbeit.quelle
Ich habe endlich eine Lösung gefunden, um den von DataGrid implementierten Standardkopiermodus zu verwenden.
Die vorherigen Antworten haben bei mir nicht funktioniert:
Ich habe endlich einen neuen Weg gefunden, um mit diesem Problem umzugehen. Sie müssen nur die Zwischenablage löschen, bevor Sie "Strg + C" drücken.
Also habe ich einen neuen Stil in den Dateiressourcen von MainWindows.xaml erstellt:
<Window.Resources> <Style TargetType="DataGrid"> <EventSetter Event="PreviewKeyDown" Handler="DataGrid_PreviewKeyDown"/> </Style> </Window.Resources>
Dieser Stil wurde entwickelt, um den "Vorschau-Schlüssel" in allen Datagrids meiner Anwendung zu verarbeiten. Die aufgerufene Methode ist die folgende:
private void DataGrid_PreviewKeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.C && (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control) { System.Windows.Forms.Clipboard.Clear(); } }
Danach wurde das Problem gelöst.
quelle
Es gibt eine DataGrid-Ereignis- / Methodensignatur für genau diesen Zweck
CopyingRowClipboardContent
(object sender
,DataGridRowClipboardEventArgs
e), die zuverlässiger alsClipboard.SetDataObject(data)
oder istClipboard.SetText(data)
.Hier erfahren Sie, wie Sie es verwenden.
Stellen Sie "FullRow" im SelectionUnit-Modus für dataGrid mit dem Namen myDataGrid ein
<DataGrid x:Name="myDataGrid" SelectionUnit="FullRow"></DataGrid>
Wir haben eine Methode,
myDataGrid_CopyingRowClipboardContent
die für jede Zeile im dataGrid aufgerufen wird, um ihren Inhalt in die Zwischenablage zu kopieren. Bei einem Datagrid mit sieben Zeilen wird dies beispielsweise sieben Mal aufgerufen.public int clipboardcalledcnt { get; set; } // CopyingRowClipboardContent invoked count private void myDataGrid_CopyingRowClipboardContent(object sender, DataGridRowClipboardEventArgs e) { PathInfo cellpath = new PathInfo(); // A custom class to hold path information string path = string.Empty; DataGrid dgdataPaths = (DataGrid)sender; int rowcnt = dgdataPaths.SelectedItems.Count; cellpath = (PathInfo)e.Item; path = "Row #" + clipboardcalledcnt + " Len=" + cellpath.Length.ToString() + ", path=" + cellpath.Path; e.ClipboardRowContent.Clear(); if (clipboardcalledcnt == 0) // Add header to clipboard paste e.ClipboardRowContent.Add(new DataGridClipboardCellContent("", null, "--- Clipboard Paste ---\t\t\n")); // \t cell divider, repeat (number of cells - 1) clipboardcalledcnt++; e.ClipboardRowContent.Add(new DataGridClipboardCellContent(path, null, path)); if (clipboardcalledcnt == rowcnt) clipboardcalledcnt = 0; }
quelle
Code app.xaml
<Application.Resources> <Style TargetType="DataGrid"> <EventSetter Event="PreviewKeyDown" Handler="DataGrid_PreviewKeyDown"/> </Style> </Application.Resources>
Codedatei app.xaml.cs
using System; using System.Collections.Generic; using System.Configuration; using System.Data; using System.Linq; using System.Threading.Tasks; using System.Windows; using System.Windows.Input; namespace WpfApp1 { /// <summary> /// Interaction logic for App.xaml /// </summary> public partial class App : Application { private void DataGrid_PreviewKeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.C && (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control) { System.Windows.Forms.Clipboard.Clear(); } } } }
Ich habe mich mit diesem Code befasst.
quelle
Ich schreibe eine Erweiterungsmethode für den WPF-Datagrid-Export nach Excel (CSV):
Wenn "MyDatagrid" der Name Ihres Datagrid ist, verwenden Sie einen Zeilencode, um die eigene Benutzersteuerung aufzurufen.
MyDatagrid.ExportToExcel(this);
und fügen Sie diese Methode Ihrer statischen Erweiterungsklasse hinzu
#region DataGrid Extentions public static void ExportToExcel(this DataGrid dg, UserControl owner, string filename = "") { try { dg.SelectionMode = DataGridSelectionMode.Extended; dg.SelectAllCells(); Clipboard.Clear(); ApplicationCommands.Copy.Execute(null, dg); var saveFileDialog = new SaveFileDialog { FileName = filename != "" ? filename : "gpmfca-exportedDocument", DefaultExt = ".csv", Filter = "Common Seprated Documents (.csv)|*.csv" }; if (saveFileDialog.ShowDialog() == true) { var clip2 = Clipboard.GetText(); File.WriteAllText(saveFileDialog.FileName, clip2.Replace('\t', ','), Encoding.UTF8); Process.Start(saveFileDialog.FileName); } dg.UnselectAllCells(); dg.SelectionMode = DataGridSelectionMode.Single; } catch (Exception ex) { owner.ShowMessageBox(ex.Message); Clipboard.Clear(); } } #endregion
endlich nicht vergessen
using Microsoft.Win32;
auf Erweiterungsklasse und setzen
ClipboardCopyMode="IncludeHeader"
für Ihr Datagrid.
quelle