How to get Main Window in UserControl - c#

I have got some generic User Control under the Canvas of the WPF window.
How do I can get that window?
I used this approach
void UserControlMethod()
{
WindowInteropHelper WindowInteropHelper = new WindowInteropHelper((Window)((Grid)(((Canvas)this.Parent).Parent)).Parent);
}
Is this correct?
Thank you!

You should use: Window.GetWindow().
The WindowInteropHelper is for interacting with native windows code or API's so that's definitely not what you want.

Related

Windows Forms Control.CreateControl() equivalent in WPF

normally I use UserControls from WinForms and can then have them created with the CreateControl() method and displayed in another application. But now I wanted to try this with WPF. But there I can't find a way to create the UserControl and then get the corresponding handle.
I tried it with
HwndSource hwndSource = PresentationSource.FromVisual(Control) as HwndSource;
if (hwndSource != null)
{
handle = hwndSource.Handle;
}
but i got no handle.
Then there is this possibility, which theoretically works, but only for Windows
IntPtr handle = new WindowInteropHelper(myWindow).EnsureHandle();
Normal Usage with WinForms Controls on a Sample:
MyCoolControl control = new MyCoolControl();
control.CreateControl();
SendHandleToSomethingElse(control.Handle.ToInt32());
and now i need this for WPF :D
Unlike a Windows Forms control, a WPF control doesn't have its own HWND handle.
In WPF only the top-level window has a handle and the controls are rendered as content inside this HWND.
Please refer to the docs for more information about how WPF uses HWNDs.

Setting a WinForms Form as Owner for a WPF Window

I have a main application which is built around a System.Windows.Forms.Form There is a legacy System.Windows.Window that the user can call up which is set as Topmost. I would like the Window to be owned by the main application, so it will minimize when the application is minimized.
So my expected code was
TopmostDisplayWindow.Owner = MainAppForm;
However, there is no Window.Owner method that takes a Form and Window has no override of Show() that takes the owner.
Is there an easy way to get a Window for the MainAppForm or would it take something more complicated?
You can use WindowInteropHelper and set Owner property of it:
var window = new YourWPFWindow();
WindowInteropHelper helper = new WindowInteropHelper(window);
helper.Owner = this.Handle;
window.Show();
Use the above code in your main/parent form which is a Winform Form.
Remember to add following references when you want to show your WPF Window:
PresentationCore
PresentationFramework
WindowsBase

WPF modal window as tool window in WinForms disappears

I was wondering if anyone can help me with this rather baffling situation. I have a WPF form myForm which I am displaying modally in a WinForm application (without using an ElementHost). Everything works fine if I use the default WindowStyle and it is shown in the taskbar. However now I don't want the form to show in the taskbar or contain the minimize button, therefore I have done the following:
MyForm myForm = new MyForm();
myForm.ShowInTaskbar = false;
myForm.WindowStyle = System.Windows.WindowStyle.ToolWindow;
myForm.WindowStartupLocation =System.Windows.WindowStartupLocation.CenterOwner;
myForm.ShowDialog();
Now, the wpf form displays as expected modally and without the minimize button. If I now select the "parent" winform application in the taskbar, the wpf form disappears and there doesn't seem to be any way of returning to it! I have read this which is similar but not the same (pure WPF application), so I can understand why the main app does not appear in the ALT+TAB menu, but can anyone tell me how I can return to the wpf form?
Thanks in advance.
The use of WindowsInteropHelper allows you to wrap a hosted WPF-form using a Winforms-form and set its parent as a Winforms control, which prevents the WPF form from disappearing (as also pointed out by dowhilefor and Hans Passant)
E.g.:
// Use the interop helper for the specified wpf window hosted by the win32 owner
WindowInteropHelper wih = new WindowInteropHelper(wpfForm);
wih.Owner = this.someWin32FormsControl.Handle;
This is not related to Winforms or WPF, this is the way Windows functions. The only solution that I think you have is to wire up your modality; that is intercept the Activated event on your Winforms form and if your WPF tool window is visible, bring that window forward and give it focus.

Is it absolutely safe to display a WPF window from a WinForms form?

I would like to display a WPF window from a windows forms application (.NET 3.5).
This code seems to work without any problem in a sample project:
public partial class WinFormsForm1 : Form
{
public WinFormsForm1() {
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e) {
WpfWindow1 w = new WpfWindow1();
w.Show();
}
}
The form is started from Main() as a normal Winforms form:
Application.Run(new WinFormsForm1());
This seems to me too easy to be true. Are there any shortcomings in this? Is this safe to do?
It has one serious shortcoming: the modeless WPF window would not get keyboard input.
The EnableModelessKeyboardInterop method call needs to be added before the WPF window is shown:
WpfWindow1 w = new WpfWindow1();
System.Windows.Forms.Integration.ElementHost.EnableModelessKeyboardInterop(w);
w.Show();
ElementHost resides in WindowsFormsIntegration.dll.
Further reading: http://msdn.microsoft.com/en-us/library/aa348549.aspx
Bottom line: it is.
We have pretty heavy application combining both WPF and winforms: windows, user controls, modal dialogs, you name it... and it's working in the medical market.
We've got into some dark corners, one is the infamous EnableModelessKeyboardInterop, another is having the WPF window be the child of the Winforms window, which you can read Here
It is really that simple. I can't think of any downside doing it this way.

Truly modal window possible?

Or would I have to do something like create a windows form and host the xaml inside it? Trying to get as consistent a look and feel as I can. If I can only do the latter, how do I achieve that?
This should be what you want:
var window = new MyWindow();
var helper = new WindowInteropHelper(window);
helper.Owner = this.Handle;
window.ShowDialog();
This is the key to ensuring correct behaviour upon minimise/restore. See this blog post for more information about the method.
(If this isn't quite what you need, perhaps you could define "truly modal".)
You can create custom dialog boxes, and they're modal. You can host a WPF Window within it and define buttons as modal closing buttons. That seems to be the best way to do a modal window, IMO.

Categories