I have an excel AddIn which exposes IWin32Window as it's main UI.
I want to show a WPF window that uses this as it's parent.
How do I go about doing that ?
You can use WindowInteropHelper to parent the WPF window appropriately:
var helper = new WindowInteropHelper(theWpfWindow);
helper.Owner = win32Window.Handle;
theWpfWindow.Show(); // This is now parented appropriately
I think you need to use a WindowInteropHelper, like shown here: IWin32Window Owner For WPF Window
Related
I am in a Win Form application, somewhere in a document I need to call this dialog written in wpf and I want to set the window.owner. The only thing close I found to get the main window of my application is the following.
I want to set the Window.Owner with a Process.GetCurrentProcess().MainWindowHandle, but have no idea how to cast the window handle into a window.
The WindowInteropHelper class allows you to set the owner of a WPF Window using an HWND (as an IntPtr).
In your case, it should be:
WindowInteropHelper wih = new WindowInteropHelper(theWpfWindow);
wih.Owner = Process.GetCurrentProcess().MainWindowHandle;
theWpfWindow.ShowDialog();
I am using ShowDialog() with WindowStyle = WindowStyle.SingleBorderWindow; to open a modal window in my WPF (MVVM) application, but it lets me navigate to parent window using the Windows taskbar (Windows 7).
I've found an answer here: WPF and ShowDialog() but it isn't suitable for me because I don't need an "always on top" tool window.
Thanks in advance
Try setting the Owner property of the dialog. That should work.
Window dialog = new Window();
dialog.Owner = mainWindow;
dialog.ShowDialog();
Edit:
I had a similar problem using this with MVVM. You can solve this by using delegates.
public class MainWindowViewModel
{
public delegate void ShowDialogDelegate(string message);
public ShowDialogDelegate ShowDialogCallback;
public void Action()
{
// here you want to show the dialog
ShowDialogDelegate callback = ShowDialogCallback;
if(callback != null)
{
callback("Message");
}
}
}
public class MainWindow
{
public MainWindow()
{
// initialize the ViewModel
MainWindowViewModel viewModel = new MainWindowViewModel();
viewModel.ShowDialogCallback += ShowDialog;
DataContext = viewModel;
}
private void ShowDialog(string message)
{
// show the dialog
}
}
I had this problem but as the Window was being opened from a view model I didn't have a reference to the current window. To get round it I used this code:
var myWindow = new MyWindowType();
myWindow.Owner = Application.Current.Windows.OfType<Window>().SingleOrDefault(x => x.IsActive);
You can use: myWindow.Owner = Application.Current.MainWindow;
However, this method causes problems if you have three windows open like this:
MainWindow
|
-----> ChildWindow1
|
-----> ChildWindow2
Then setting ChildWindow2.Owner = Application.Current.MainWindow will set the owner of the window to be its grandparent window, not parent window.
When the parent window makes (and shows) the child window, that is where you need to set the owner.
public partial class MainWindow : Window
{
private void openChild()
{
ChildWindow child = new ChildWindow ();
child.Owner = this; // "this" is the parent
child.ShowDialog();
}
}
Aditionally, if you don't want an extra taskbar for all the children... then
<Window x:Class="ChildWindow"
ShowInTaskbar="False" >
</Window>
Much of the reason for the MVVM pattern is so that your interaction logic can be unit tested. For this reason, you should never directly open a window from the ViewModel, or you'll have dialogs popping up in the middle of your unit tests.
Instead, you should raise an event that the View will handle and open a dialog for you. For example, see this article on Interaction Requests: https://msdn.microsoft.com/en-us/library/gg405494(v=pandp.40).aspx#sec12
The problem seems to be related to Window.Owner, and indeed if you judge by previous knowledge that you might have of the Win32 API and WinForms, a missing owner would be the typical cause of such a problem, but as many have pointed out, in the case of WPF that's not it. Microsoft keeps changing things to keep things interesting.
In WPF you can have a dialog with a specific owner and you can still have the dialog appear in the taskbar. Because why not. And that's the default behavior. Because why not. Their rationale is that modal dialogs are not kosher anymore, so you should not be using them; you should be using modeless dialogs, which make sense to show as separate taskbar icons, and in any case the user can then decide whether they want to see different app windows as separate icons, or whether they want to see them grouped.
So, they are trying to enforce this policy with complete disregard to anyone who might want to go against their guidelines and create a modal dialog. So, they force you to explicitly state that you do not want a taskbar icon to appear for your dialog.
To fix this problem, do the following in the constructor of your view class:
ShowInTaskbar = false;
(This may happen right after InitializeComponent();
This is equivalent to Xcalibur37's answer, though the way I figure things, since WPF forces you to have both a .cs file and a .xaml file, you might as well put things that are unlikely to change in the .cs file.
Add "ShowInTaskbar" and set it to false.
Even if this post is a bit old, I hope it is OK that I post my solution.
All the above results are known to me and did not exactly yield the desired result.
I am doing it for the other googlers :)
Lets say f2 is your window that you want to display on top of f1 :
f2.Owner = Window.GetWindow(this);
f2.ShowDialog();
That's it , I promise it will not disappear !
HTH
Guy
I have a wpf usercontrol that contains an activex control housed in a windowsformhost.
I'm using an MVVM pattern that says
ViewModel1 is mapped to a Pure WPF View and
ViewModel2 is mapped to wpf content and the above usercontrol
If ViewModel2 is "Hidden" and then becomes Visible then the Activex control inside it doesn't show (Specifically I'm talking about the VLC activex control).
I've tested in a non MVVM pattern with a button and the usercontrol. The usercontrol is hidden until you press the button and the same thing happens but if I create a method in the usercontrol to re attach the activex control to the windowsformhost then it reappears. If I call this method from a viewmodel then it still remains blank. Does anyone know how I can get this to show again?
EDIT - I've just discovered it's because I have transparency on in my wpf application. It seems it's not possable to do what I want with windowsformshost and transparency enabled.
As there are no obvious answers I'll share my experience. When transparency is turned on in the wpf window then the windows form host doesn't refresh when changing from Hidden to Visable. I have found no way to make this work unless it is hosted in a new window with "Allowstransparency=false".
How are you setting up your active x control? The following Typically works for me in WPF if you are just needing it to attach to a grid. No user control required.:
//Active X Control initializer
private Ax addAxObject<Ax>(Grid container)
where Ax : System.Windows.Forms.Control, new()
{
Ax ax = new Ax();
var hoster = new System.Windows.Forms.Integration.WindowsFormsHost();
hoster.Child = (System.Windows.Forms.Control)ax;
container.Children.Add(hoster);
return ax;
}
private MyActiveXControl myActiveXControl;
public Grid InitializeActiveX(Grid grid)
{
myActiveXControl = addAxObject<myActiveXControl>(grid);
return grid;
}
Then all you do is is add it to your grid in your main window like so:
public MainWindow()
{
InitializeComponent();
//initialize Active X control
gridMain = InitializeActiveX(gridMain);
}
It shows up just fine for me. (Obviously not in the designer since it is programatically created)
I have an MFC MDI application and I am trying to add a new dialog to it. I want this dialog to be in WPF (a Window basically rather than a dialog). This window should be modeless and a child to the current MDI View.
Let's say I have CMyView in the MFC application, and in its OnCreate, I try to create the WPF Window. To do so, I made a wrapper class called CMyWindowWrapper (that compiles with /CLR)
int CMyView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
m_wrapper.Create(this);
return 0;
}
The window wrapper class has a Create function which actually creates the WPF Window:
void CMyWindowWrapper::Create(CWnd* pParent)
{
MyWindow^ window = gcnew MyWindow();
window->ShowModeless((IntPtr)pParent->GetSafeHwnd());
m_myWindow = window;
}
MyWindow is the WPF Window where I added a function called ShowModeless as follows:
public void ShowModeless(IntPtr parent)
{
WindowInteropHelper helper = new WindowInteropHelper(this);
helper.Owner = parent;
Show();
ShowInTaskbar = false;
}
Now the application behaves as follows: whenever a CMyView is created, a modeless MyWindow is created successfully, and it appears always on top of CMyView even if the focus is on CMyView. However, when CMyView is closed or minimized, MyWindow is not following it. It gets close/minimized only if the whole application gets closed/minimized.
I can attach a sample application showing the problem if needed.
Please advise.
Thank you so much.
An alternative solution would be to make your WPF window a user control. Create a MFC modeless dialog and put the WPF user control in the MFC modeless dialog.
i've done this before but i cannot find my old code.
how do you embed a window inside a window.
let say i created a custom form and saved it as Window1.xaml, and want to embed it in Window2.xaml, without copy and pasting the xaml code.. TIA
EDIT: i think my question is somewhat misleading, i'll rephrase it.
i have this Window1.xaml i added custom headers and background images/colors.
then in Window2.xaml, i want Window1 to be a custom control and embed it here.
not sure if its Content Presenters, still googling for the answer :)
You can't host a WPF Window inside another WPF Window, but you could move the content from one Window to another:
var window1 = new Window1();
var window2 = new Window2();
var content = window1.Content;
window1.Content = null;
window2.Content = content;
Note that you set window1.Content to null or else you get an exception, since the content will have a visual parent otherwise.
UPDATE
It appears all you need to do is to copy all the XAML between the <Window></Window> tags in Window1 into a new UserControl, then host that user control in Window2.
I believe you should make use of Pages or usercontrols in such cases. This way you can navigate to other parts/pages/controls defined in application. CodeKaizen is right , you can't host a window inside another window
I'm not sure you can do that - however, you shouldn't put the user interface directly into a window, use a normal control (either custom or user) instead and reuse that in your windows.
I know you can do it in code behind
//Window you want to show
Window1 child = new Window1();
object content = child.Content;
child.Content = null;
//Where to show
this.grid1.Children.Clear();
this.grid1.Children.Add((UIElement)content);
Hope helps!
It sounds like you really want a UserControl. Change Window1's type from Window to UserControl and then put that UserControl in Window2.