5
votes

Scenario

I have the following scenario (I've stripped it down to a sample application):

  • A WPF application with a window (MainWindow) hosting a WinForms UserControl (UserControl1).
    • The control is added dynamically in the code behind to a WindowsFormsHost
  • UserControl1 has a button which opens a form (Form1)
    • It uses form1.Show(this).

Problem is:

  • Form1's .Owner property is null.
    • In the real application, some work is done involving the .Owner property which means I can't just ignore this problem. Ideally, of course, there wouldn't be any dependancy here.
    • In the real application, I don't have control over the WinForms side of this code. Our WPF application is hosting another team's WinForms control.
    • Notes:
      • When I use a WinForms host instead, the .Owner property is set correctly.
      • UserControl1 is hosted fine in all other ways -- in the real application everything else works fine, it's just that the form opened by the user control doesn't have a proper owner.

I can understand why there's a problem here, but I'm hoping the answer to my next question might be 'yes'!

Is there anything I can do to get this to work by making changes on the WPF side of the equation?

Failing that, could anything be done on the WinForms side? (it's not beyond the realms of possibility that I could get some changes implemented there...)

Sample Code

Here's the code in my sample app. First the WPF side:

<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;

    }
}

And now the WinForms side...

UserControl1 is just a user control with a button and a label on it. Here's the code:

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 is just an empty form.

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

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

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

The Owner shown in the message box and the TopLevelControl shown in the label are null when hosted in WPF, but have a value when hosted in another WinForms application.

Further Investigation

I guess the problem here is that .Owner is of type Form and there's no instance of this type in the WPF application. It's hard to imagine what valid value that property could have in this scenario. It seems likely, therefore, that I need to get the code changed that's accessing the `.Owner' property in Form1.

1

1 Answers

1
votes
<Window
  xmlns:my="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration" 
>

<my:WindowsFormsHost  Name="MapHost" ScrollViewer.CanContentScroll="False"  SizeChanged="MapHost_SizeChanged" />

MapControl inherits System.Windows.Forms.Control

MapHost.Child = MapControl;