【问题标题】:How to host WPF application in Winform using reflection如何使用反射在 Winform 中托管 WPF 应用程序
【发布时间】:2013-10-03 13:18:48
【问题描述】:

我有一个简单的 WPF 应用程序 MyWPF.exe,

namespace MyWPF
{
     /// <summary>
     /// Interaction logic for MainWindow.xaml
     /// </summary>
   public partial class MainWindow : Window
   {           

    public MainWindow()
    {
        InitializeComponent();

    }

    private void button1_Click(object sender, RoutedEventArgs e)
    {
     MessageBox.Show("Button is clicked");
    }
  }
}

我想在我的 Winform 应用程序中加载这个“MainWindow”,我尝试如下,创建实例时出现异常 “System.InvalidOperationException: Window must be the root of the tree. Cannot add Window as视觉的孩子。”

        String path = @"D:\Test\MyForm\MyWPF\bin\Debug\MyWPF.exe";
        System.Reflection.Assembly myExeApp = System.Reflection.Assembly.LoadFile(path);
        System.Type MyWPFType = myExeApp.GetType("MyWPF.MainWindow");

        var MyWPFInstance = (System.Windows.Window)myExeApp.CreateInstance("MyWPF.MainWindow");

        ctrlHost = new ElementHost();
        ctrlHost.Dock = DockStyle.Fill;
        ElementHost.EnableModelessKeyboardInterop(MyWPFInstance );
        ctrlHost.Child = MyWPFInstance ;
        this.Controls.Add(ctrlHost);

有可能还是我错过了什么?整个异常如下,

System.InvalidOperationException: Window must be the root of the tree. Cannot add Window as a child of Visual.
   at System.Windows.Window.OnAncestorChanged()
   at System.Windows.FrameworkElement.OnAncestorChangedInternal(TreeChangeInfo parentTreeState)
   at System.Windows.TreeWalkHelper.OnAncestorChanged(DependencyObject d, TreeChangeInfo info)
   at System.Windows.DescendentsWalker`1.StartWalk(DependencyObject startNode, Boolean skipStartNode)
   at MS.Internal.PrePostDescendentsWalker`1.StartWalk(DependencyObject startNode, Boolean skipStartNode)
   at System.Windows.TreeWalkHelper.InvalidateOnTreeChange(FrameworkElement fe, FrameworkContentElement fce, DependencyObject parent, Boolean isAddOperation)
   at System.Windows.FrameworkElement.ChangeLogicalParent(DependencyObject newParent)
   at System.Windows.FrameworkElement.AddLogicalChild(Object child)
   at System.Windows.Controls.UIElementCollection.AddInternal(UIElement element)
   at System.Windows.Controls.UIElementCollection.Add(UIElement element)
   at System.Windows.Forms.Integration.ElementHost.set_Child(UIElement value)
   at MyForm.Form1.button1_Click(Object sender, EventArgs e) in D:\Test\MyForm\MyForm\Form1.cs:line 37
   at System.Windows.Forms.Control.OnClick(EventArgs e)
   at System.Windows.Forms.Button.OnClick(EventArgs e)
   at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
   at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
   at System.Windows.Forms.Control.WndProc(Message& m)
   at System.Windows.Forms.ButtonBase.WndProc(Message& m)
   at System.Windows.Forms.Button.WndProc(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

【问题讨论】:

  • 听起来你不能在控件中放置一个窗口。看起来还挺合理的。为什么不使用其他类型的容器,而不是向您的控制主机添加一个窗口?也许是网格或其他面板?
  • 但是我可以在 Winform 中使用 Winform 来做到这一点。
  • 我当然不怀疑,但是如果您要完全重新设计 API(如 WPF),您可能会考虑限制在技术上没有意义的事情(如将窗口放在窗口内)。此外,如果它不允许您使用窗口,您可以将窗口更改为从UserControl(而不是Window)派生,问题就解决了。
  • 但是我们正在尝试在我们的 Winform 应用程序中嵌入第三方 WPF 应用程序。
  • 对,请注意异常说“Window 必须是树的根,而不是 Form 必须是树的根”,这意味着异常是从 WPF 生成的,而不是从 Winforms 生成的。这是 WPF 约束。其他人也遇到了同样的问题:(stackoverflow.com/questions/1772768/avalondock-dock-a-window)。

标签: c# .net wpf winforms winforms-interop


【解决方案1】:

ElementHost 不适用于这种互操作。您可以使用任何非Window 控件作为其子控件。您可以重构 WPF 应用程序,使主窗口包含一个用户控件,您将使用反射代码加载该控件并添加到表单中。

或者,您可以使用 Win32 SetParent 将 WPF 窗口放置为 Windows 窗体控件的子级,但我绝对会避免这样做。

【讨论】:

  • 我就是想试试,请问怎么做?
【解决方案2】:

我知道,这是一个老问题,但也许其他人也在寻找解决方案。

只需输入以下代码: ElementHost.EnableModelessKeyboardInterop(this); 在每个 WPF 窗口中 InitializeComponent(); 之前。

它帮助了我。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-09
    • 1970-01-01
    • 2014-03-24
    • 1970-01-01
    相关资源
    最近更新 更多