2

重现我的案例(.net 4.0)

  1. 创建 WPF 应用程序 (MainWindow.xaml)
  2. 添加包含文本框的 Winform 用户控件 (UserConrol1.cs - Winform)
  3. 使用 windowsformshost 将 UserControl1 放入 MainWindow.xaml
  4. 将另一个包含文本框 (wpf) 的 WPF 窗口添加到项目 (Window1.xaml)
  5. 在 MainWindow InitializeComponent 之后创建并显示 Window1

您的项目已准备就绪,

  1. 运行项目并在 MainWindow.xaml 中设置文本框(在 WindowsFormsHost 中)
  2. 通过打开一个窗口(Windows 文件资源管理器、记事本、winamp 等)停用您的应用程序
  3. 尝试通过用鼠标单击文本框在 Window1 窗口中的文本框中写入

而且您会看到您无法在 Window1 中的文本框上设置焦点,因为 MainWindow Texbox(在 winformshost 中会窃取您对激活的应用程序的关注)

任何的想法?

主窗口.xaml

<Window x:Class="WinFormsHostFocusProblem.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WinFormsHostFocusProblem"
        xmlns:my="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
      <my:WindowsFormsHost  Focusable="False"  >
         <local:UserControl1>

         </local:UserControl1>
      </my:WindowsFormsHost>

   </Grid>
</Window>

主窗口.xaml.cs

namespace WinFormsHostFocusProblem
{
   public partial class MainWindow : Window
   {
      public MainWindow()
      {
         InitializeComponent();
         Window1 window1 = new Window1();
         window1.Show();
      }
   }
}

Window1.xaml

<Window x:Class="WinFormsHostFocusProblem.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WinFormsHostFocusProblem"
        xmlns:my="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
        SizeToContent="WidthAndHeight" 
        ResizeMode="NoResize"

        Topmost="True"
        Title="Window1" Height="300" Width="300" Background="Red">
    <Grid>
      <TextBox Height="25">asd</TextBox>
   </Grid>
</Window>

Window1.xaml.cs

namespace WinFormsHostFocusProblem
{
   public partial class Window1 : Window
   {
      public Window1()
      {
         InitializeComponent();
      }
   }
}
4

2 回答 2

5

我使用我的 MSDN 支持合同来得到这个问题的答案。工程师能够从 yunusayd 的样本中重现,并确认它几乎肯定是 WindowsFormsHost 中的一个错误。

感谢 yunus 提供了最小的重现样本,感谢 Microsoft 的 Keith 解决了这个问题并在不到一天的时间内提供了解决方法。

解决方法代码如下。它通过使用 .NET 反射来更改 WindowsFormsHost 中使用的私有变量并禁用该错误的触发器来工作。据我一起工作的工程师说,这依赖于 WPF 内部,但他与产品团队成员交谈过,应该可以安全使用。当然,不能保证没有副作用,但到目前为止,我在多个 WPF 窗口中使用多个 WindowsFormsHost 进行测试时没有发现任何问题(也许嵌套会更棘手)。我修改了原始的解决方法,使其可以在多个窗口中通用。您可以在 Application_Deactivated 事件中轻松硬编码对特定窗口和命名 WindowsFormsHost 控件的引用,并跳过整个“LastActive”方案和扩展方法。

// App.xaml.cs: you must hook up to Application.Deactivated
void Application_Deactivated(object sender, EventArgs e)
{
    foreach (Window w in windows)
    {
        foreach (var host in UI.DependencyObjectExtension.AllLogicalChildren(w).
                     Where(c => c is WindowsFormsHost))
        {
            FIELD_FOCUSED_CHILD.SetValue(host, null);
        }
    }
}


public readonly static FieldInfo FIELD_FOCUSED_CHILD = typeof(System.Windows.Forms.Integration.WindowsFormsHost).
    GetField("_focusedChild", BindingFlags.NonPublic | BindingFlags.Instance);

public static class DependencyObjectExtension
{
    /// <summary>
    /// Returns a collection of o's logical children, recursively.
    /// </summary>
    /// <param name="o"></param>
    /// <returns></returns>
    public static IEnumerable<DependencyObject> AllLogicalChildren(this DependencyObject o)
    {
        foreach (var child in LogicalTreeHelper.GetChildren(o))
        {
            if (child is DependencyObject)
            {
                yield return (DependencyObject)child;

                if (child is DependencyObject)
                {
                    foreach (var innerChild in AllLogicalChildren((DependencyObject)child))
                    {
                        yield return innerChild;
                    }
                }
            }
        }
    }
}
于 2012-03-02T14:14:43.243 回答
0

我们在我们的一个应用程序中遇到了类似的问题,发现升级到 .net 4.5 似乎已经修复了我们应用程序的大部分 WPF/WinForms 焦点问题,包括与此类似的问题。

另外,.net 4.5 版本的 WindowsFormsHost 中不再存在 _focusedChild 字段

于 2013-04-05T23:18:27.183 回答