【问题标题】:Creating a form from a WinForms Control hosted within WPF -- Owner is not set从 WPF 中托管的 WinForms 控件创建表单 -- 未设置所有者
【发布时间】:2012-12-11 17:30:46
【问题描述】:

场景

我有以下场景(我已将其简化为示例应用程序):

  • 一个 WPF 应用程序,其窗口 (MainWindow) 托管 WinForms UserControl (UserControl1)。
    • 控件在后面的代码中动态添加到WindowsFormsHost
  • UserControl1 有一个打开表单的按钮 (Form1)
    • 它使用form1.Show(this)

问题是:

  • Form1.Owner 属性为空。
    • 在实际应用程序中,一些工作涉及.Owner 属性,这意味着我不能忽略这个问题。当然,理想情况下,这里不会有任何依赖。
    • 在实际应用程序中,我无法控制此代码的 WinForms 端。我们的 WPF 应用程序正在托管另一个团队的 WinForms 控件。
    • 注意事项:
      • 当我改用 WinForms 主机时,.Owner 属性设置正确。
      • UserControl1 在所有其他方面都可以很好地托管 - 在实际应用程序中,其他一切都可以正常工作,只是用户控件打开的表单 没有适当的所有者.

我能理解这里为什么会出现问题,但我希望我的下一个问题的答案可能是“是”!

我可以做些什么来通过在等式的 WPF 方面进行更改来使其正常工作?

如果做不到这一点,在 WinForms 方面可以做些什么吗? (我可以在那里进行一些更改,这并不超出可能的范围......)

示例代码

这是我的示例应用程序中的代码。首先是WPF方面:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:my="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="700">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Button Name="btnAdd" Click="btnAdd_Click" Content="Add Winform"/>

        <WindowsFormsHost Grid.Row="1" Name="host" ScrollViewer.CanContentScroll="False"/>
    </Grid>
</Window>
public partial class MainWindow : Window
{
    private WindowsFormsHost host;

    public MainWindow()
    {
        InitializeComponent();
    }

    private void btnAdd_Click(object sender, RoutedEventArgs e)
    {
        UserControl1 uc1 = new UserControl1();
        WindowsFormsHost.EnableWindowsFormsInterop();
        this.host.Child = uc1;

    }
}

现在是 WinForms 方面...

UserControl1 只是一个带有按钮和标签的用户控件。代码如下:

public partial class UserControl1 : UserControl
    {
        public UserControl1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Form1 form1 = new Form1();
            form1.Show(this);
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            this.label1.Text = "this: " + this + Environment.NewLine + "parent: " + this.Parent + Environment.NewLine + "toplevelcontrol: " + this.TopLevelControl;
        }
    }

Form1 只是一个空表单。

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);

        MessageBox.Show(" this: " + this + " owner: " + this.Owner);
    }
}

消息框中显示的Owner 和标签中显示的TopLevelControl 在 WPF 中托管时为 null,但在其他 WinForms 应用程序中托管时具有值。

进一步调查

我想这里的问题是.Owner 的类型是Form,并且在 WPF 应用程序中没有这种类型的实例。很难想象在这种情况下该属性可能具有什么有效价值。因此,我似乎需要更改访问 Form1 中的 `.Owner' 属性的代码。

【问题讨论】:

    标签: c# wpf winforms winforms-interop


    【解决方案1】:
    <Window
      xmlns:my="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration" 
    >
    
    <my:WindowsFormsHost  Name="MapHost" ScrollViewer.CanContentScroll="False"  SizeChanged="MapHost_SizeChanged" />
    

    MapControl 继承 System.Windows.Forms.Control

    MapHost.Child = MapControl;
    

    【讨论】:

    • 感谢您的支持 -- 但是,我已经在我的 btnAdd_Click() 方法中使用了 WindowsFormsHost。我也尝试过直接在 XAML 中声明主机控件,但在没有所有者的情况下打开后续表单仍然存在问题。我会尝试在我的问题中澄清这一点。
    • 好的,我修改了我的问题,将 WindowsFormsHost 放在 XAML 中,而不是在 btnAdd_Click() 中实例化它。不幸的是,我仍然遇到同样的问题。
    • @doornail... 你试过设置所有者吗??? MyForm.Owner = this (WPF 窗口);
    • 不幸的是我不能这样做,因为窗体是由 WinForms 用户控件创建的,而不是由 WPF 窗口本身创建的。我希望 usercontrol1 仍然能够调用 form1.Show(this)。当用户控件位于 WinForms 窗体上时,这可以正常工作(form1 的所有者设置为该父窗体)。当它在 WPF 窗口上时,所有者是 null
    猜你喜欢
    • 1970-01-01
    • 2013-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-03
    • 2012-03-27
    • 1970-01-01
    相关资源
    最近更新 更多