2

私のケースを再現するには(.net 4.0)

  1. WPF アプリケーション (MainWindow.xaml) を作成する
  2. テキスト ボックス (UserConrol1.cs - Winform) を含む Winform ユーザー コントロールを追加します。
  3. Windowsformshost を使用して UserControl1 を MainWindow.xaml に配置します。
  4. テキストボックス (wpf) を含む別の WPF ウィンドウをプロジェクト (Window1.xaml) に追加します。
  5. MainWindow InitializeComponent の後に Window1 を作成して表示する

プロジェクトの準備が整いました。

  1. Project を実行し、MainWindow.xaml (WindowsFormsHost にあるもの) にフォーカスされたテキスト ボックスを設定します。
  2. ウィンドウを開いてアプリケーションを非アクティブ化します (Windows ファイル エクスプローラー、メモ帳、winamp など)。
  3. マウスでテキストボックスをクリックして、Window1ウィンドウのテキストボックスに書き込んでみてください

また、Window1 のテキストボックスにフォーカスを設定できないことがわかります。これは、MainWindow Texbox (winformshost では、アプリケーションがアクティブになったときにフォーカスが奪われるためです)

何か案が?

MainWindow.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>

MainWindow.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 と、問題に取り組み、1 日もかからずに回避策を提供してくれた Microsoft の Keith に感謝します。

回避策のコードは次のとおりです。.NET リフレクションを使用して、WindowsFormsHost で使用されるプライベート変数を変更し、バグのトリガーを無効にすることで機能します。私が一緒に働いたエンジニアによると、これは WPF 内部に依存していますが、彼は製品チームのメンバーと話し、安全に使用できるはずです。もちろん、副作用がないという保証はありませんが、これまでのところ、複数の WPF ウィンドウで複数の WindowsFormsHosts を使用したテストで問題は見つかりませんでした (入れ子にする方が難しいかもしれません)。複数のウィンドウで一般的に機能するように、元の回避策を変更しました。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 に答える