Blog
ObservableCollection & ArgumentException
Eine Geschichte über DataBinding, ObservableCollection und ArgumentException ( Das Objekt mit dem Typ System.EventHandler kann nicht in den Typ System.EventHandler`1[ EventArgs ] konvertiert werden. ).
Neulich hab ich eine Solution vom Arbeitsplatz zu mir nach Hause geschickt, um Daheim weiter arbeiten zu können.
Zuhause kam allerdings die erste Ernüchterung. Ich hab die Solution geöffnet, compiliert und gestartet. Alles schien in Ordnung zu sein, bis... ich die Applikation schloß.
Dann wurde eine ArgumentException gefeuert. Aber warum? Kurz zusammengefasst ging es um...
Meine Solution beinhaltete eine Klasse die 2 eigens definierte EventHandler hat. Diese Klasse habe ich mit Daten gefüllt und in eine ObservableCollection gestopft. Anschließend habe ich diese an eine ListBox gebunden.
data.Add(new Detail(DateTime.Now, 1));
_listBox1.ItemsSource = data;
Hier die genauere Fehlermeldung:
System.ArgumentException was unhandled
Message="Das Objekt mit dem Typ System.EventHandler kann nicht in den Typ System.EventHandler`1[DetailChangedEventArgs] konvertiert werden."
Source="mscorlib"
StackTrace:
bei System.RuntimeType.CheckValue(Object value, Binder binder, CultureInfo culture, BindingFlags invokeAttr)
bei System.Reflection.MethodBase.CheckArguments(Object[] parameters, Binder binder, BindingFlags invokeAttr, CultureInfo culture, Signature sig)
bei System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
bei System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
bei System.ComponentModel.ReflectEventDescriptor.RemoveEventHandler(Object component, Delegate value)
bei System.ComponentModel.ReflectPropertyDescriptor.RemoveValueChanged(Object component, EventHandler handler)
bei MS.Internal.Data.ValueChangedEventManager.ValueChangedRecord.StopListening()
bei MS.Internal.Data.ValueChangedEventManager.Purge(Object source, Object data, Boolean purgeAll)
bei MS.Internal.WeakEventTable.Purge(Boolean purgeAll)
bei MS.Internal.WeakEventTable.OnDispatcherShutDown(Object sender, EventArgs e)
bei System.EventHandler.Invoke(Object sender, EventArgs e)
bei System.Windows.Threading.Dispatcher.ShutdownImplInSecurityContext(Object state)
bei System.Threading.ExecutionContext.runTryCode(Object userData)
bei System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
bei System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
bei System.Windows.Threading.Dispatcher.ShutdownImpl()
bei System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
bei System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
bei System.Windows.Threading.Dispatcher.Run()
bei System.Windows.Application.RunInternal(Window window)
bei System.Windows.Application.Run(Window window)
bei System.Windows.Application.Run()
bei WPFDataBinding.App.Main() in C:UsersmartinDocumentsVisual Studio 2008Code SnippetsVisual C#My Code SnippetsWPFDataBindingWPFDataBindingobjDebugApp.g.cs:Zeile 0.
bei System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
bei System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
bei Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
bei System.Threading.ThreadHelper.ThreadStart_Context(Object state)
bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
bei System.Threading.ThreadHelper.ThreadStart()
Nach längerem herumprobieren stellte ich fest, dass diese Exception nur auftrat wenn mein EventHandler wie folgt aussah:
public event EventHandler<DetailChangedEventArgs> DetailChanged;
Änderte ich den Namen aber auf public event EventHandler<DetailChangedEventArgs> adfsfdDetailChanged; tratt keine Exception auf.
Deshalb nehme ich an, dass beim DataBinden des EventHandler der Typ nicht überprüft wird. Wird das DataBinding aber beendet und es findet ein "unhook" statt, so wird wahrscheinlich ein Code erzeugt der wie folgt aussieht:
EventHandler itemchanged = ...; item.TagChanged -= itemchanged;
Das kann aber nicht funktionieren, da der angemeldete EventHandler einen anderen Typ hat. Der Fehler tritt erst während der Laufzeit auf, da der code dynamisch compiliert wird.
Es wäre möglich, dass beim "start" des DataBind nach NAMEChanged Events gesucht wird. Danach klinkt sich das DataBinding ein. Das wäre ein logischer Grund warum die etwas merkwürdige Fehlerumgehung funktioniert.
Kurz darauf habe ich auf Connect genau das gleiche Fehlerverhalten vorgefunden.
Ich hab mir die Solution mit der ArgumentException wieder zurück auf die Arbeit geschickt. Komischerweise tratt dort dieser Fehler aber nicht mehr auf. Ich konnte die Anwendung Fehlerfrei kompilieren und auch Fehlerlos beenden. Falls trotzdem jemand diesen etwas merkwürdigen "Bug" hat kann er folgendes dagegen tun:
keinen eigenens def. EventHandler verwenden
den EventHandler umbennen in etwas andres als NAMEChanged
So sollte man das umgehen können. Falls jemand auch auf diesen Bug gestoßen ist und eine bessere Lösung hat, kann er sich gerne bei mir melden .
Links zum Thema:
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=88707
Schlüsselwörter: C#
zuletzt geändert: 30. Jänner 2009 21:47
Link zu diesem Artikel: (in die Zwischenablage)
(c) 2011 | Impressum |
| Empfehlenswerte Blog Einträgebaska.jpg)