Getting the parent window from the most inner WPF usercontrol

282 Views Asked by At

I have an WPF User control, let's say UCInner, which contains a WPF Popup. UCInner is used in another WPF user control, let's say UCOuter.

UCOuter is embedded in an ElementHost (ElementHost.Child = UCOuter).

Finally UCOuter is embedded within an Outlook VSTO custom task pane ahd this latter used in a winforms application (Outlook VSTO Add-in).

So from the most inner WPF Control, UCInner, I would like to obtain the parent Window. I have tried some alternatives with no success, I am always getting null or exceptions:

Window w = Window.GetWindow(myPopup);
Window w = Window.GetWindow(UCInner);

I also have tried what explained here and also this one.

  • UPDATED - ANOTHER ATTEMPT:

I have tried below piece of code and i can get successfully the window handle, but now from the handle I need to get the Window Object.

dynamic activeWindow = Globals.ThisAddIn.Application.ActiveWindow();
Microsoft.VisualStudio.OLE.Interop.IOleWindow win = activeWindow as Microsoft.VisualStudio.OLE.Interop.IOleWindow;

IntPtr handle;
win.GetWindow(out handle);

So in order to get the Window object I have tried this based on the Window handle:

System.Windows.Interop.HwndSource hwndSource = System.Windows.Interop.HwndSource.FromHwnd(handle);

Window w = hwndSource.RootVisual as Window;

but this does not work, hwndSource is null.

2

There are 2 best solutions below

8
On

If you need to figure out the right parent window to display your own WPF window, cast Application.ActiveWindow to IOleWindow (Application.ActiveWindow can return either Explorer or Inspector, they both support IOleWindow) and call IOleWindow.GetWindow. Once you have the HWND, create an instance of the WindowInteropHelper class and specify the Outlook window handle as the parent:

if (outlookHwnd != IntPtr.Zero)
{
    WindowInteropHelper helper = new WindowInteropHelper(YourDialogWindow);
    helper.Owner = outlookHwnd;
    YourDialogWindow.ShowInTaskbar = false;
}
14
On

First, you need to retrieve the parent window handle, in case of Explorer window in Outlook you can use:

Outlook.Explorer explorer = OutlookApplication.ActiveExplorer();
IOleWindow oleWindow = explorer as IOleWindow;
IntPtr handle = IntPtr.Zero;

oleWindow.GetWindow(out handle);

if (handle != IntPtr.Zero)
{
    WindowInteropHelper helper = new WindowInteropHelper(DialogWindow);
    helper.Owner = handle;
    DialogWindow.ShowInTaskbar = false;
    DialogWindow.ShowDialog();
}

where IOleWindow can be defined in the following way:

/// <summary>
/// Implemented and used by containers and objects to obtain window handles
/// and manage context-sensitive help.
/// </summary>
/// <remarks>
/// The IOleWindow interface provides methods that allow an application to obtain
/// the handle to the various windows that participate in in-place activation,
/// and also to enter and exit context-sensitive help mode.
/// </remarks>
[ComImport]
[Guid("00000114-0000-0000-C000-000000000046")]
[InterfaceType (ComInterfaceType.InterfaceIsIUnknown)]
public interface IOleWindow
{
    /// <summary>
    /// Returns the window handle to one of the windows participating in in-place activation
    /// (frame, document, parent, or in-place object window).
    /// </summary>
    /// <param name="phwnd">Pointer to where to return the window handle.</param>
    void GetWindow (out IntPtr phwnd) ;

    /// <summary>
    /// Determines whether context-sensitive help mode should be entered during an
    /// in-place activation session.
    /// </summary>
    /// <param name="fEnterMode"><c>true</c> if help mode should be entered;
    /// <c>false</c> if it should be exited.</param>
    void ContextSensitiveHelp ([In, MarshalAs(UnmanagedType.Bool)] bool fEnterMode) ;
}