System.ArgumentException se produit avec WindowsFormsHost dans une Application WPF


Pas sûr que ce soit le bon ? Nous avons ajouté ce problème à notre image mémoire diagnostic qui peut confirmer.

Symptômes


Vous avez développé une application Microsoft .NET 4.0 qui utilise WPF et l’élément WindowsFormsHost pour héberger des contrôles Windows Forms. Lors de l’utilisation de l’application, vous recevez l’exception suivante.

System.ArgumentException : Invisible ou contrôle désactivé ne peut pas être activé.
à System.Windows.Forms.ContainerControl.SetActiveControlInternal (valeurs de contrôle)
à System.Windows.Forms.ContainerControl.SetActiveControl (ctl de contrôle)
à System.Windows.Forms.ContainerControl.set_ActiveControl (valeurs de contrôle)
à System.Windows.Forms.Integration.WindowsFormsHost.RestoreFocusedChild()
à System.Windows.Forms.Control.InvokeMarshaledCallbackDo (tme ThreadMethodEntry)
à System.Windows.Forms.Control.InvokeMarshaledCallbackHelper (Object obj)
à System.Threading.ExecutionContext.runTryCode (objet userData)
à System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup (code de TryCode, CleanupCode backoutCode, userData de l’objet)
à System.Threading.ExecutionContext.RunInternal (ExecutionContext executionContext, rappel de ContextCallback, état de l’objet)
à System.Threading.ExecutionContext.Run (ExecutionContext executionContext ContextCallback rappel, état de l’objet, Boolean ignoreSyncCtx)
à System.Threading.ExecutionContext.Run (ExecutionContext executionContext, rappel de ContextCallback, état de l’objet)
à System.Windows.Forms.Control.InvokeMarshaledCallback (tme ThreadMethodEntry)
à System.Windows.Forms.Control.InvokeMarshaledCallbacks()


Cause


Il s’agit d’un bogue confirmé dans WPF dans .NET Framework 4.0.

Résolution


Vous pouvez contourner ce problème de plusieurs manières.

1. ne supprimez pas les contrôles par programmation à partir de l’élément WindowsFormsHost. Au lieu de cela, les masquer en affectant à la propriété Visible.

2. fils d’un eventhandler pour l’événement System.Windows.Forms.Application.ThreadException. Cela vous permettra de supprimer de la boîte de dialogue Windows Forms exception. Le code peut vérifier spécifiquement si l’exception est une exception System.ArgumentException est à partir de System.Windows.Forms, qui contient « System.Windows.Forms.Integration.WindowsFormsHost.RestoreFocusedChild » dans sa pile des appels. Si ce n’est pas le cas, puis afficher la boîte de dialogue d’exception Windows Forms standard.


MainWindow() public
        {
System.Windows.Forms.Application.ThreadException += System.Threading.ThreadExceptionEventHandler(Application_ThreadException) nouveau ;
        }

void Application_ThreadException (object émetteur, System.Threading.ThreadExceptionEventArgs e)
        {
if ( !. FailureFromFocusedChild(e.Exception))
            {
Dlg de System.Windows.Forms.Application.ThreadExceptionDialog ;
Dlg = System.Windows.Forms.Application.ThreadExceptionDialog(e.Exception) nouvelle ;
Dlg. ShowDialog() ;
            }

private bool FailureFromFocusedChild (Exception e)
        {
résultat bool = false ;
chaîne stackTrace = e.StackTrace ;
           
résultat = (e est System.ArgumentException) & & (e.Source == « System.Windows.Forms »)
                    && (stackTrace.IndexOf("System.Windows.Forms.Integration.WindowsFormsHost.RestoreFocusedChild")>=0);


renvoyer les résultats ;
        }

Plus d'informations


WindowsFormsHost utilise une procédure de fenêtre substituée pour analyser les messages de fenêtre WM_ACTIVATEAPP afin de déterminer si l’application hôte est en cours activé ou désactivé.

Si l’application hôte est en cours de désactivation, puis WindowsFormsHost vérifie si la fenêtre qui a le focus d’entrée est une fenêtre enfant de l’élément WindowsFormsHost. S’il s’agit, WindowsFormsHost met en cache une référence à ce contrôle dans un champ interne. WindowsFormsHost utilise ce champ pour définir le contrôle actif une fois que l’application est activée à un moment ultérieur.

Si l’application hôte est en cours d’activation, puis WindowsFormsHost vérifie si ce champ interne est non nulle. Si elle est non nulle, il s’exécuter en mode asynchrone de la méthode System.Windows.Forms.Integration.WindowsFormsHost.RestoreFocusedChild. Cette méthode définit le champ interne mis en cache précédemment Control.ActiveControl.

Le problème se produit lorsque le contrôle qui avait été mise en cache a été supprimé de l’élément WindowsFormsHost, une fois que l’application a été désactivée. Par exemple, cela peut se produire si l’application utilise les événements de Application.Deactivated de WPF pour supprimer les contrôles de l’élément WindowsFormsHost.