Windows Form opening WPF window
I have a Windows Form project containing a Windows Form that opens a blank WPF window with a TextBox control and the text is not displaying within the TextBox with keyboard input.
If I copy the XAML to a WPF .NET 3.0 project the text will be displayed within the TextBox. However within my normal VB.NET Windows Form project the TextBox is not displaying the key presses when the WPF window is opened from a Windows Form. Does something need to be added to the project to ensure that the WPF controls will work fine when opened from a Windows Form?
XAML code is as follows:
<Window x:Class="Window1"
xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation
xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml
Title="Window" Height="512" Width="727">
<Grid>
<FlowDocumentScrollViewer Margin="20,60,20,98" Name="FlowDocumentScrollViewer" />
<TextBox Height="61" Margin="23,0,117,21" Name="TextBox" VerticalAlignment="Bottom" TextWrapping="Wrap" FlowDirection="LeftToRight" RenderOptions.BitmapScalingMode="Unspecified"></TextBox>
</Grid>
</Window>Also, I did some testing and checking the KeyDown event does output the keys that are pressed. Simply the key is not being displayed within the WPF window / textBox.
Even when creating a WPF project and adding a Windows Form to that project the issue will still occur. The only way to not have the issue to occur is to use a WPF form and load the WPF window using the App.xaml file. Is there a workaround for this so that a Windows Form can be loaded and then WPF windows can be loaded from that Windows Form window.
It seems that when this is done the events are not working properly within the WPF window. Any ideas?
Answers
Proper input interop with a non-WPF host (such as WinForms) requires some cooperation between the host and the WPF input system. The topic Sharing Message Loops Between Win32 and WPF in the SDK explains this well. At a minimum, you have to call ComponentDispatcher.RaiseThreadMessage() from the host’s message loop. In your setup, the easiest way to make this happen is to use code like this:
Window w = new Window1();
System.Windows.Forms.Integration.ElementHost.EnableModelessKeyboardInterop(w);
w.Show();
ElementHost.EnableModelessKeyboardInterop() essentially registers an input hook with the WinForms Application object (which normally runs the message loop) and calls ComponentDispatcher.RaiseThreadMessage().
All Replies
Proper input interop with a non-WPF host (such as WinForms) requires some cooperation between the host and the WPF input system. The topic Sharing Message Loops Between Win32 and WPF in the SDK explains this well. At a minimum, you have to call ComponentDispatcher.RaiseThreadMessage() from the host’s message loop. In your setup, the easiest way to make this happen is to use code like this:
Window w = new Window1();
System.Windows.Forms.Integration.ElementHost.EnableModelessKeyboardInterop(w);
w.Show();
ElementHost.EnableModelessKeyboardInterop() essentially registers an input hook with the WinForms Application object (which normally runs the message loop) and calls ComponentDispatcher.RaiseThreadMessage().
- This can also do the trick:
Window wnd = new Window();
wnd.Show();System.Windows.Threading.Dispatcher.Run();
Sheva- Proposed As Answer byEricc Antunes Friday, August 07, 2009 1:48 PM
- For a hybrid application, this is not a correct solution in general. Running the WPF message loop alone (which the Dispatcher does) can deprive WinForms of some of the messages it needs. In particular, tabbing within a winform/window is likely to be broken.
- You are right, Chango, and also if you open the WPF window as a modal dialog, the problem disappears, I believe the nested message pump will internally call the ComponentDispatcher.RaiseThreadMessage() method.
Sheva - How would you do this when embedding a WPF UserControl inside a Windows Form? The EnableModelessKeyboardInterop function only takes a Window (not a UserControl) and according to my limited knowledge of WPF you can't embed a WPF Window inside a Windows Form.
Any ideas? - Use the ElementHost class to host WPF controls, preferably UserControl-based, in WinForms.
- Right, I've already got my WPF UserControl-derived object inside an ElementHost which is inside a Form. The problem is getting keyboard input to my object. I can't seem to use ElementHost.EnableModelessKeyboardInterop(Window) because it takes a Window, not a UserControl. How do you get around this?
- In this setup, ElementHost should be doing the input delegation/handling for the hosted WPF control. If you let WinForms run the message loop normally, you shouldn't have to do anything special. Please describe more about the structure of your application and what specific problem you are having. It may be good to start a new thread, since this one was originally about top-level windows, and the issues are somewhat different.
- Ok, I created a new thread here: http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2664391&SiteID=1

