Notice: This website is an unofficial Microsoft Knowledge Base (hereinafter KB) archive and is intended to provide a reliable access to deleted content from Microsoft KB. All KB articles are owned by Microsoft Corporation. Read full disclaimer for more details.

System.ArgumentException Occurs With WindowsFormsHost in WPF Application


Not sure if this is the right fix? We've added this issue to our memory dump diagnostic which can confirm.

↑ Back to the top


Symptoms

You have developed a Microsoft .NET 4.0 application which uses WPF and the WindowsFormsHost element in order to host Windows Forms controls. When using the application, you receive the following exception.

System.ArgumentException: Invisible or disabled control cannot be activated
   at System.Windows.Forms.ContainerControl.SetActiveControlInternal(Control value)
   at System.Windows.Forms.ContainerControl.SetActiveControl(Control ctl)
   at System.Windows.Forms.ContainerControl.set_ActiveControl(Control value)
   at System.Windows.Forms.Integration.WindowsFormsHost.RestoreFocusedChild()
   at System.Windows.Forms.Control.InvokeMarshaledCallbackDo(ThreadMethodEntry tme)
   at System.Windows.Forms.Control.InvokeMarshaledCallbackHelper(Object obj)
   at System.Threading.ExecutionContext.runTryCode(Object userData)
   at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Windows.Forms.Control.InvokeMarshaledCallback(ThreadMethodEntry tme)
   at System.Windows.Forms.Control.InvokeMarshaledCallbacks()


↑ Back to the top


Cause

This is due to a confirmed bug in WPF in the .NET 4.0 Framework.

↑ Back to the top


Resolution

You can work around this behavior in these ways.

1. Do not programmatically remove controls from the WindowsFormsHost element. Instead, hide them by setting their Visible property.

2. Wire an eventhandler to the System.Windows.Forms.Application.ThreadException event. This will allow you to suppress the Windows Forms exception dialog. The code can check specifically to see if the exception is a System.ArgumentException from System.Windows.Forms, that contains "System.Windows.Forms.Integration.WindowsFormsHost.RestoreFocusedChild" in its call stack. If not, then display the standard Windows Forms exception dialog box.


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

        void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
        {
            if (!FailureFromFocusedChild(e.Exception))
            {
                System.Windows.Forms.Application.ThreadExceptionDialog dlg;
                dlg = new System.Windows.Forms.Application.ThreadExceptionDialog(e.Exception);
                dlg.ShowDialog();
            }

        private bool FailureFromFocusedChild(Exception e)
        {
            bool result = false;
            string stackTrace = e.StackTrace;
           
            result = (e is System.ArgumentException) && (e.Source == "System.Windows.Forms")
                    && (stackTrace.IndexOf("System.Windows.Forms.Integration.WindowsFormsHost.RestoreFocusedChild")>=0);


            return result;
        }

↑ Back to the top


More Information

WindowsFormsHost uses an overridden window procedure to monitor for WM_ACTIVATEAPP window messages in order to determine if the host applicaiton is being activated or deactivated.

If the host application is being deactivated, then WindowsFormsHost checks to see if the window with the input focus is a child window of the WindowsFormsHost element. If it is, then WindowsFormsHost caches a reference to that Control within an internal field. WindowsFormsHost will use this field to set as the active control once the application is activated at a later time.

If the host application is being activated, then WindowsFormsHost checks to see if that internal field is non-null. If it is non-null, it will asynchronously execute the System.Windows.Forms.Integration.WindowsFormsHost.RestoreFocusedChild method. This method will set Control.ActiveControl to the internal field cached earlier.

The problem occurs when the Control which had been cached has been removed from the WindowsFormsHost element after the application was deactivated. For example, this can occur if the application uses WPF's Application.Deactivated event in order to remove controls from the WindowsFormsHost element.

↑ Back to the top


Keywords: kb

↑ Back to the top

Article Info
Article ID : 2686194
Revision : 1
Created on : 1/7/2017
Published on : 10/9/2014
Exists online : False
Views : 144